diff --git a/Octokit.Reactive/Clients/IObservablePackageVersionsClient.cs b/Octokit.Reactive/Clients/IObservablePackageVersionsClient.cs
new file mode 100644
index 00000000..5d2f0045
--- /dev/null
+++ b/Octokit.Reactive/Clients/IObservablePackageVersionsClient.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Reactive;
+
+namespace Octokit.Reactive
+{
+ public interface IObservablePackageVersionsClient
+ {
+ ///
+ /// List all versions of a package.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Optional: Return packages with a state. Defaults to Active
+ /// Optional: Paging options
+ IObservable GetAllForOrg(string org, PackageType packageType, string packageName, PackageVersionState state = PackageVersionState.Active, ApiOptions options = null);
+
+ ///
+ /// Get a specific version of a package.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+
+ IObservable GetForOrg(string org, PackageType packageType, string packageName, int packageVersionId);
+
+ ///
+ /// Deletes a specific package version in an organization.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ IObservable DeleteForOrg(string org, PackageType packageType, string packageName, int packageVersionId);
+
+ ///
+ /// Restores a specific package version in an organization.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ IObservable RestoreForOrg(string org, PackageType packageType, string packageName, int packageVersionId);
+
+ ///
+ /// Returns all package versions for a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Optional: Return packages with a state. Defaults to Active
+ /// Optional: Paging options
+ IObservable GetAllForActiveUser(PackageType packageType, string packageName, PackageVersionState state = PackageVersionState.Active, ApiOptions options = null);
+
+ ///
+ /// Gets a specific package version for a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ IObservable GetForActiveUser(PackageType packageType, string packageName, int packageVersionId);
+
+ ///
+ /// Deletes a specific package version for a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ IObservable DeleteForActiveUser(PackageType packageType, string packageName, int packageVersionId);
+
+ ///
+ /// Restores a package version owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ IObservable RestoreForActiveUser(PackageType packageType, string packageName, int packageVersionId);
+
+ ///
+ /// Returns all package versions for a public package owned by a specified user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Optional: Return packages with a state. Defaults to Active
+ /// Optional: Paging options
+ IObservable GetAllForUser(string username, PackageType packageType, string packageName, PackageVersionState state = PackageVersionState.Active, ApiOptions options = null);
+
+ ///
+ /// Gets a specific package version for a public package owned by a specified user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ IObservable GetForUser(string username, PackageType packageType, string packageName, int packageVersionId);
+
+ ///
+ /// Deletes a specific package version for a user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ IObservable DeleteForUser(string username, PackageType packageType, string packageName, int packageVersionId);
+
+ ///
+ /// Restores a specific package version for a user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ IObservable RestoreForUser(string username, PackageType packageType, string packageName, int packageVersionId);
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Reactive/Clients/IObservablePackagesClient.cs b/Octokit.Reactive/Clients/IObservablePackagesClient.cs
new file mode 100644
index 00000000..6814cad8
--- /dev/null
+++ b/Octokit.Reactive/Clients/IObservablePackagesClient.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Reactive;
+
+namespace Octokit.Reactive
+{
+ public interface IObservablePackagesClient
+ {
+ IObservablePackageVersionsClient PackageVersions { get; }
+
+ ///
+ /// List all packages for an organisations, readable by the current user
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Optional: The visibility of the package
+ IObservable GetAllForOrg(string org, PackageType packageType, PackageVisibility? packageVisibility = null);
+
+ ///
+ /// Get a specific package for an Organization.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ IObservable GetForOrg(string org, PackageType packageType, string packageName);
+
+ ///
+ /// Delete a specific package for an Organization.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ IObservable DeleteForOrg(string org, PackageType packageType, string packageName);
+
+ ///
+ /// Restore a specific package for an Organization.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ IObservable RestoreForOrg(string org, PackageType packageType, string packageName);
+
+ ///
+ /// Lists packages owned by the authenticated user within the user's namespace
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Optional: The visibility of the package
+ IObservable GetAllForActiveUser(PackageType packageType, PackageVisibility? packageVisibility = null);
+
+ ///
+ /// Gets a specific package for a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ IObservable GetForActiveUser(PackageType packageType, string packageName);
+
+ ///
+ /// Deletes a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ IObservable DeleteForActiveUser(PackageType packageType, string packageName);
+
+ ///
+ /// Restores a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ IObservable RestoreForActiveUser(PackageType packageType, string packageName);
+
+ ///
+ /// Lists packages owned by the authenticated user within the user's namespace
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Optional: The visibility of the package
+ IObservable GetAllForUser(string username, PackageType packageType, PackageVisibility? packageVisibility = null);
+
+ ///
+ /// Gets a specific package metadata for a public package owned by a user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ IObservable GetForUser(string username, PackageType packageType, string packageName);
+
+ ///
+ /// Deletes an entire package for a user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ IObservable DeleteForUser(string username, PackageType packageType, string packageName);
+
+ ///
+ /// Restores an entire package for a user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ IObservable RestoreForUser(string username, PackageType packageType, string packageName);
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Reactive/Clients/ObservablePackageVersionsClient.cs b/Octokit.Reactive/Clients/ObservablePackageVersionsClient.cs
new file mode 100644
index 00000000..f6ad28d7
--- /dev/null
+++ b/Octokit.Reactive/Clients/ObservablePackageVersionsClient.cs
@@ -0,0 +1,253 @@
+using Octokit.Reactive.Internal;
+using System;
+using System.Reactive;
+using System.Reactive.Threading.Tasks;
+
+namespace Octokit.Reactive
+{
+ public class ObservablePackageVersionsClient : IObservablePackageVersionsClient
+ {
+ readonly IPackageVersionsClient _client;
+ readonly IConnection _connection;
+
+ public ObservablePackageVersionsClient(IGitHubClient client)
+ {
+ Ensure.ArgumentNotNull(client, nameof(client));
+
+ _client = client.Packages.PackageVersions;
+ _connection = client.Connection;
+ }
+
+ ///
+ /// List all versions of a package.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Optional: Return packages with a state. Defaults to Active
+ /// Optional: Paging options
+ public IObservable GetAllForOrg(string org, PackageType packageType, string packageName, PackageVersionState state = PackageVersionState.Active, ApiOptions options = null)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.ApiOptionsNotNull(ref options);
+
+ var route = ApiUrls.PackageVersionsOrg(org, packageType, packageName);
+ var parameters = ParameterBuilder.AddParameter("state", state);
+
+ return _connection.GetAndFlattenAllPages(route, parameters);
+ }
+
+ ///
+ /// Get a specific version of a package.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ public IObservable GetForOrg(string org, PackageType packageType, string packageName, int packageVersionId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.GreaterThanZero(packageVersionId, nameof(packageVersionId));
+
+ return _client.GetForOrg(org, packageType, packageName, packageVersionId).ToObservable();
+ }
+
+ ///
+ /// Deletes a specific package version in an organization.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ public IObservable DeleteForOrg(string org, PackageType packageType, string packageName, int packageVersionId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.GreaterThanZero(packageVersionId, nameof(packageVersionId));
+
+ return _client.DeleteForOrg(org, packageType, packageName, packageVersionId).ToObservable();
+ }
+
+ ///
+ /// Restores a specific package version in an organization.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ public IObservable RestoreForOrg(string org, PackageType packageType, string packageName, int packageVersionId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.GreaterThanZero(packageVersionId, nameof(packageVersionId));
+
+ return _client.RestoreForOrg(org, packageType, packageName, packageVersionId).ToObservable();
+ }
+
+ ///
+ /// Returns all package versions for a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Optional: Return packages with a state. Defaults to Active
+ /// Optional: Paging options
+ public IObservable GetAllForActiveUser(PackageType packageType, string packageName, PackageVersionState state = PackageVersionState.Active, ApiOptions options = null)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.ApiOptionsNotNull(ref options);
+
+ var route = ApiUrls.PackageVersionsActiveUser(packageType, packageName);
+ var parameters = ParameterBuilder.AddParameter("state", state);
+
+ return _connection.GetAndFlattenAllPages(route, parameters);
+ }
+
+ ///
+ /// Gets a specific package version for a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ public IObservable GetForActiveUser(PackageType packageType, string packageName, int packageVersionId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.GreaterThanZero(packageVersionId, nameof(packageVersionId));
+
+ return _client.GetForActiveUser(packageType, packageName, packageVersionId).ToObservable();
+ }
+
+ ///
+ /// Deletes a specific package version for a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ public IObservable DeleteForActiveUser(PackageType packageType, string packageName, int packageVersionId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.GreaterThanZero(packageVersionId, nameof(packageVersionId));
+
+ return _client.DeleteForActiveUser(packageType, packageName, packageVersionId).ToObservable();
+ }
+
+ ///
+ /// Restores a package version owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ public IObservable RestoreForActiveUser(PackageType packageType, string packageName, int packageVersionId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.GreaterThanZero(packageVersionId, nameof(packageVersionId));
+
+ return _client.RestoreForActiveUser(packageType, packageName, packageVersionId).ToObservable();
+ }
+
+ ///
+ /// Returns all package versions for a public package owned by a specified user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Optional: Return packages with a state. Defaults to Active
+ /// Optional: Paging options
+ public IObservable GetAllForUser(string username, PackageType packageType, string packageName, PackageVersionState state = PackageVersionState.Active, ApiOptions options = null)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(username, nameof(username));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.ApiOptionsNotNull(ref options);
+
+ var route = ApiUrls.PackageVersionsUser(username, packageType, packageName);
+ var parameters = ParameterBuilder.AddParameter("state", state);
+
+ return _connection.GetAndFlattenAllPages(route, parameters);
+ }
+
+ ///
+ /// Gets a specific package version for a public package owned by a specified user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ public IObservable GetForUser(string username, PackageType packageType, string packageName, int packageVersionId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(username, nameof(username));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.GreaterThanZero(packageVersionId, nameof(packageVersionId));
+
+ return _client.GetForUser(username, packageType, packageName, packageVersionId).ToObservable();
+ }
+
+ ///
+ /// Deletes a specific package version for a user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ public IObservable DeleteForUser(string username, PackageType packageType, string packageName, int packageVersionId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(username, nameof(username));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.GreaterThanZero(packageVersionId, nameof(packageVersionId));
+
+ return _client.DeleteForUser(username, packageType, packageName, packageVersionId).ToObservable();
+ }
+
+ ///
+ /// Restores a specific package version for a user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ /// Required: The id of the package version
+ public IObservable RestoreForUser(string username, PackageType packageType, string packageName, int packageVersionId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(username, nameof(username));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+ Ensure.GreaterThanZero(packageVersionId, nameof(packageVersionId));
+
+ return _client.RestoreForUser(username, packageType, packageName, packageVersionId).ToObservable();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Reactive/Clients/ObservablePackagesClient.cs b/Octokit.Reactive/Clients/ObservablePackagesClient.cs
new file mode 100644
index 00000000..662efb55
--- /dev/null
+++ b/Octokit.Reactive/Clients/ObservablePackagesClient.cs
@@ -0,0 +1,235 @@
+using Octokit.Reactive.Internal;
+using System;
+using System.Reactive;
+using System.Reactive.Threading.Tasks;
+
+namespace Octokit.Reactive
+{
+ public class ObservablePackagesClient : IObservablePackagesClient
+ {
+ readonly IPackagesClient _client;
+ readonly IConnection _connection;
+
+ public ObservablePackagesClient(IGitHubClient client)
+ {
+ Ensure.ArgumentNotNull(client, nameof(client));
+
+ _client = client.Packages;
+ _connection = client.Connection;
+ }
+
+ public IObservablePackageVersionsClient PackageVersions { get; private set; }
+
+ ///
+ /// List all packages for an organisations, readable by the current user
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Optional: The visibility of the package
+ public IObservable GetAllForOrg(string org, PackageType packageType, PackageVisibility? packageVisibility = null)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+
+ var route = ApiUrls.PackagesOrg(org);
+ var parameters = ParameterBuilder.AddParameter("package_type", packageType).AddOptionalParameter("visibility", packageVisibility);
+
+ return _connection.GetAndFlattenAllPages(route, parameters);
+ }
+
+ ///
+ /// Get a specific package for an Organization.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ public IObservable GetForOrg(string org, PackageType packageType, string packageName)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+
+ return _client.GetForOrg(org, packageType, packageName).ToObservable();
+ }
+
+ ///
+ /// Delete a specific package for an Organization.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ public IObservable DeleteForOrg(string org, PackageType packageType, string packageName)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+
+ return _client.DeleteForOrg(org, packageType, packageName).ToObservable();
+ }
+
+ ///
+ /// Restore a specific package for an Organization.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Organisation Name
+ /// Required: The type of package
+ /// Required: The name of the package
+ public IObservable RestoreForOrg(string org, PackageType packageType, string packageName)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+
+ return _client.RestoreForOrg(org, packageType, packageName).ToObservable();
+ }
+
+ ///
+ /// Lists packages owned by the authenticated user within the user's namespace
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Optional: The visibility of the package
+ public IObservable GetAllForActiveUser(PackageType packageType, PackageVisibility? packageVisibility = null)
+ {
+ var route = ApiUrls.PackagesActiveUser();
+ var parameters = ParameterBuilder.AddParameter("package_type", packageType).AddOptionalParameter("visibility", packageVisibility);
+
+ return _connection.GetAndFlattenAllPages(route, parameters);
+ }
+
+ ///
+ /// Gets a specific package for a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ public IObservable GetForActiveUser(PackageType packageType, string packageName)
+ {
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+
+ return _client.GetForActiveUser(packageType, packageName).ToObservable();
+ }
+
+ ///
+ /// Deletes a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ public IObservable DeleteForActiveUser(PackageType packageType, string packageName)
+ {
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+
+ return _client.DeleteForActiveUser(packageType, packageName).ToObservable();
+ }
+
+ ///
+ /// Restores a package owned by the authenticated user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: The type of package
+ /// Required: The name of the package
+ public IObservable RestoreForActiveUser(PackageType packageType, string packageName)
+ {
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+
+ return _client.RestoreForActiveUser(packageType, packageName).ToObservable();
+ }
+
+ ///
+ /// Lists packages owned by the authenticated user within the user's namespace
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Optional: The visibility of the package
+ public IObservable GetAllForUser(string username, PackageType packageType, PackageVisibility? packageVisibility = null)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(username, nameof(username));
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+
+ var route = ApiUrls.PackagesUser(username);
+ var parameters = ParameterBuilder.AddParameter("package_type", packageType).AddOptionalParameter("visibility", packageVisibility);
+
+ return _connection.GetAndFlattenAllPages(route, parameters);
+ }
+
+ ///
+ /// Gets a specific package metadata for a public package owned by a user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ public IObservable GetForUser(string username, PackageType packageType, string packageName)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(username, nameof(username));
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+
+ return _client.GetForUser(username, packageType, packageName).ToObservable();
+ }
+
+ ///
+ /// Deletes an entire package for a user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ public IObservable DeleteForUser(string username, PackageType packageType, string packageName)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(username, nameof(username));
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+
+ return _client.DeleteForUser(username, packageType, packageName).ToObservable();
+ }
+
+ ///
+ /// Restores an entire package for a user.
+ ///
+ ///
+ /// See the API documentation for more details
+ ///
+ /// Required: Username
+ /// Required: The type of package
+ /// Required: The name of the package
+ public IObservable RestoreForUser(string username, PackageType packageType, string packageName)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(username, nameof(username));
+ Ensure.ArgumentNotNull(packageType, nameof(packageType));
+ Ensure.ArgumentNotNullOrEmptyString(packageName, nameof(packageName));
+
+ return _client.RestoreForUser(username, packageType, packageName).ToObservable();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Reactive/IObservableGitHubClient.cs b/Octokit.Reactive/IObservableGitHubClient.cs
index e4f91ec0..5563afe5 100644
--- a/Octokit.Reactive/IObservableGitHubClient.cs
+++ b/Octokit.Reactive/IObservableGitHubClient.cs
@@ -34,5 +34,6 @@ namespace Octokit.Reactive
IObservableMigrationClient Migration { get; }
IObservableReactionsClient Reaction { get; }
IObservableChecksClient Check { get; }
+ IObservablePackagesClient Packages{ get; }
}
}
\ No newline at end of file
diff --git a/Octokit.Reactive/ObservableGitHubClient.cs b/Octokit.Reactive/ObservableGitHubClient.cs
index a063faae..e84e191b 100644
--- a/Octokit.Reactive/ObservableGitHubClient.cs
+++ b/Octokit.Reactive/ObservableGitHubClient.cs
@@ -49,6 +49,7 @@ namespace Octokit.Reactive
Migration = new ObservableMigrationClient(gitHubClient);
Reaction = new ObservableReactionsClient(gitHubClient);
Check = new ObservableChecksClient(gitHubClient);
+ Packages = new ObservablePackagesClient(gitHubClient);
}
public IConnection Connection
@@ -88,6 +89,7 @@ namespace Octokit.Reactive
public IObservableMigrationClient Migration { get; private set; }
public IObservableReactionsClient Reaction { get; private set; }
public IObservableChecksClient Check { get; private set; }
+ public IObservablePackagesClient Packages { get; private set; }
///
/// Gets the latest API Info - this will be null if no API calls have been made
diff --git a/Octokit.Tests.Integration/Clients/PackageVersionsClientTests.cs b/Octokit.Tests.Integration/Clients/PackageVersionsClientTests.cs
new file mode 100644
index 00000000..2571500d
--- /dev/null
+++ b/Octokit.Tests.Integration/Clients/PackageVersionsClientTests.cs
@@ -0,0 +1,34 @@
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Octokit.Tests.Integration.Clients
+{
+ public class PackageVersionsClientTests
+ {
+ public class TheGetAllMethod
+ {
+ [IntegrationTest(Skip = "Cannot create packages as part of this test, so can never succeed")]
+ public async Task ReturnsAllPackageVersions()
+ {
+ var github = Helper.GetAuthenticatedClient();
+
+ var result = await github.Packages.PackageVersions.GetAllForOrg(Helper.Organization, PackageType.Container, "asd");
+
+ Assert.NotEmpty(result);
+ }
+ }
+
+ public class TheGetMethod
+ {
+ [IntegrationTest(Skip = "Cannot create packages as part of this test, so can never succeed")]
+ public async Task ReturnsAPackages()
+ {
+ var github = Helper.GetAuthenticatedClient();
+
+ var result = await github.Packages.PackageVersions.GetForOrg(Helper.Organization, PackageType.Container, "asd", 1);
+
+ Assert.NotNull(result);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Tests.Integration/Clients/PackagesClientTests.cs b/Octokit.Tests.Integration/Clients/PackagesClientTests.cs
new file mode 100644
index 00000000..f1e2ab00
--- /dev/null
+++ b/Octokit.Tests.Integration/Clients/PackagesClientTests.cs
@@ -0,0 +1,34 @@
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Octokit.Tests.Integration.Clients
+{
+ public class PackagesClientTests
+ {
+ public class TheGetAllMethod
+ {
+ [IntegrationTest(Skip = "Cannot create packages as part of this test, so can never succeed")]
+ public async Task ReturnsAllPackages()
+ {
+ var github = Helper.GetAuthenticatedClient();
+
+ var result = await github.Packages.GetAllForOrg(Helper.Organization, PackageType.Container);
+
+ Assert.NotEmpty(result);
+ }
+ }
+
+ public class TheGetMethod
+ {
+ [IntegrationTest(Skip = "Cannot create packages as part of this test, so can never succeed")]
+ public async Task ReturnsAPackages()
+ {
+ var github = Helper.GetAuthenticatedClient();
+
+ var result = await github.Packages.GetForOrg(Helper.Organization, PackageType.Container, "asd");
+
+ Assert.NotNull(result);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Tests/Clients/PackageVersionsClientTests.cs b/Octokit.Tests/Clients/PackageVersionsClientTests.cs
new file mode 100644
index 00000000..2e75aa33
--- /dev/null
+++ b/Octokit.Tests/Clients/PackageVersionsClientTests.cs
@@ -0,0 +1,395 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using NSubstitute;
+using Xunit;
+
+namespace Octokit.Tests.Clients
+{
+ public class PackageVersionsClientTests
+ {
+ public class TheCtor
+ {
+ [Fact]
+ public void EnsuresNonNullArguments()
+ {
+ Assert.Throws(() => new PackageVersionsClient(null));
+ }
+ }
+
+ public class TheGetAllForOrgMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.GetAllForOrg("fake", PackageType.RubyGems, "name");
+
+ connection.Received().GetAll(Arg.Is(u =>
+ u.ToString() == "/orgs/fake/packages/rubygems/name/versions"),
+ Arg.Is>(d => d.ContainsKey("state")),
+ Args.ApiOptions);
+ }
+
+ [Fact]
+ public async Task RequestsCorrectUrlWithOptionalParameter()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.GetAllForOrg("fake", PackageType.RubyGems, "name", PackageVersionState.Deleted);
+
+ var calls = connection.ReceivedCalls();
+ connection.Received().GetAll(Arg.Is(u =>
+ u.ToString() == "/orgs/fake/packages/rubygems/name/versions"),
+ Arg.Is>(d => d.ContainsKey("state") && d["state"] == "deleted"),
+ Args.ApiOptions);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await Assert.ThrowsAsync(() => client.GetAllForOrg(null, PackageType.Npm, "asd"));
+ await Assert.ThrowsAsync(() => client.GetAllForOrg("", PackageType.Npm, "asd"));
+
+ await Assert.ThrowsAsync(() => client.GetAllForOrg("owner", PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.GetAllForOrg("owner", PackageType.Npm, ""));
+ }
+ }
+
+ public class TheGetForOrgMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.GetForOrg("fake", PackageType.Npm, "name", 5);
+
+ connection.Received().Get(Arg.Is(u => u.ToString() == "/orgs/fake/packages/npm/name/versions/5"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackageVersionsClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.GetForOrg(null, PackageType.Npm, "asd", 5));
+ await Assert.ThrowsAsync(() => client.GetForOrg("", PackageType.Npm, "asd", 5));
+
+ await Assert.ThrowsAsync(() => client.GetForOrg("owner", PackageType.Npm, null, 5));
+ await Assert.ThrowsAsync(() => client.GetForOrg("owner", PackageType.Npm, "", 5));
+
+ await Assert.ThrowsAsync(() => client.GetForOrg("owner", PackageType.Npm, "", 0));
+ }
+ }
+
+ public class TheDeleteForOrgMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.DeleteForOrg("fake", PackageType.Npm, "name", 5);
+
+ connection.Received().Delete(Arg.Is(u => u.ToString() == "/orgs/fake/packages/npm/name/versions/5"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackageVersionsClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.DeleteForOrg(null, PackageType.Npm, "asd", 5));
+ await Assert.ThrowsAsync(() => client.DeleteForOrg("", PackageType.Npm, "asd", 5));
+
+ await Assert.ThrowsAsync(() => client.DeleteForOrg("owner", PackageType.Npm, null, 5));
+ await Assert.ThrowsAsync(() => client.DeleteForOrg("owner", PackageType.Npm, "", 5));
+
+ await Assert.ThrowsAsync(() => client.DeleteForOrg("owner", PackageType.Npm, "", 0));
+ }
+ }
+
+ public class TheRestoreForOrgMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.RestoreForOrg("fake", PackageType.Npm, "name", 5);
+
+ connection.Received().Post(Arg.Is(u => u.ToString() == "/orgs/fake/packages/npm/name/versions/5/restore"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackageVersionsClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.RestoreForOrg(null, PackageType.Npm, "asd", 5));
+ await Assert.ThrowsAsync(() => client.RestoreForOrg("", PackageType.Npm, "asd", 5));
+
+ await Assert.ThrowsAsync(() => client.RestoreForOrg("owner", PackageType.Npm, null, 5));
+ await Assert.ThrowsAsync(() => client.RestoreForOrg("owner", PackageType.Npm, "", 5));
+
+ await Assert.ThrowsAsync(() => client.RestoreForOrg("owner", PackageType.Npm, "", 0));
+ }
+ }
+
+ public class TheGetAllForActiveUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.GetAllForActiveUser(PackageType.RubyGems, "name");
+
+ connection.Received().GetAll(Arg.Is(u =>
+ u.ToString() == "/user/packages/rubygems/name/versions"),
+ Arg.Is>(d => d.ContainsKey("state")),
+ Args.ApiOptions);
+ }
+
+ [Fact]
+ public async Task RequestsCorrectUrlWithOptionalParameter()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.GetAllForActiveUser(PackageType.RubyGems, "name", PackageVersionState.Deleted);
+
+ var calls = connection.ReceivedCalls();
+ connection.Received().GetAll(Arg.Is(u =>
+ u.ToString() == "/user/packages/rubygems/name/versions"),
+ Arg.Is>(d => d.ContainsKey("state") && d["state"] == "deleted"),
+ Args.ApiOptions);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await Assert.ThrowsAsync(() => client.GetAllForActiveUser(PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.GetAllForActiveUser(PackageType.Npm, ""));
+ }
+ }
+
+ public class TheGetForActiveUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.GetForActiveUser(PackageType.Npm, "name", 5);
+
+ connection.Received().Get(Arg.Is(u => u.ToString() == "/user/packages/npm/name/versions/5"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackageVersionsClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.GetForActiveUser(PackageType.Npm, null, 5));
+ await Assert.ThrowsAsync(() => client.GetForActiveUser(PackageType.Npm, "", 5));
+
+ await Assert.ThrowsAsync(() => client.GetForActiveUser(PackageType.Npm, "", 0));
+ }
+ }
+
+ public class TheDeleteForActiveUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.DeleteForActiveUser(PackageType.Npm, "name", 5);
+
+ connection.Received().Delete(Arg.Is(u => u.ToString() == "/user/packages/npm/name/versions/5"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackageVersionsClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.DeleteForActiveUser(PackageType.Npm, null, 5));
+ await Assert.ThrowsAsync(() => client.DeleteForActiveUser(PackageType.Npm, "", 5));
+
+ await Assert.ThrowsAsync(() => client.DeleteForActiveUser(PackageType.Npm, "", 0));
+ }
+ }
+
+ public class TheRestoreForActiveUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.RestoreForActiveUser(PackageType.Npm, "name", 5);
+
+ connection.Received().Post(Arg.Is(u => u.ToString() == "/user/packages/npm/name/versions/5/restore"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackageVersionsClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.RestoreForActiveUser(PackageType.Npm, null, 5));
+ await Assert.ThrowsAsync(() => client.RestoreForActiveUser(PackageType.Npm, "", 5));
+
+ await Assert.ThrowsAsync(() => client.RestoreForActiveUser(PackageType.Npm, "", 0));
+ }
+ }
+
+ public class TheGetAllForUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.GetAllForUser("fake", PackageType.RubyGems, "name");
+
+ connection.Received().GetAll(Arg.Is(u =>
+ u.ToString() == "/users/fake/packages/rubygems/name/versions"),
+ Arg.Is>(d => d.ContainsKey("state")),
+ Args.ApiOptions);
+ }
+
+ [Fact]
+ public async Task RequestsCorrectUrlWithOptionalParameter()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.GetAllForUser("fake", PackageType.RubyGems, "name", PackageVersionState.Deleted);
+
+ var calls = connection.ReceivedCalls();
+ connection.Received().GetAll(Arg.Is(u =>
+ u.ToString() == "/users/fake/packages/rubygems/name/versions"),
+ Arg.Is>(d => d.ContainsKey("state") && d["state"] == "deleted"),
+ Args.ApiOptions);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await Assert.ThrowsAsync(() => client.GetAllForUser(null, PackageType.Npm, "asd"));
+ await Assert.ThrowsAsync(() => client.GetAllForUser("", PackageType.Npm, "asd"));
+
+ await Assert.ThrowsAsync(() => client.GetAllForUser("owner", PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.GetAllForUser("owner", PackageType.Npm, ""));
+ }
+ }
+
+ public class TheGetForUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.GetForUser("fake", PackageType.Npm, "name", 5);
+
+ connection.Received().Get(Arg.Is(u => u.ToString() == "/users/fake/packages/npm/name/versions/5"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackageVersionsClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.GetForUser(null, PackageType.Npm, "asd", 5));
+ await Assert.ThrowsAsync(() => client.GetForUser("", PackageType.Npm, "asd", 5));
+
+ await Assert.ThrowsAsync(() => client.GetForUser("owner", PackageType.Npm, null, 5));
+ await Assert.ThrowsAsync(() => client.GetForUser("owner", PackageType.Npm, "", 5));
+
+ await Assert.ThrowsAsync(() => client.GetForUser("owner", PackageType.Npm, "", 0));
+ }
+ }
+
+ public class TheDeleteForUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.DeleteForUser("fake", PackageType.Npm, "name", 5);
+
+ connection.Received().Delete(Arg.Is(u => u.ToString() == "/users/fake/packages/npm/name/versions/5"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackageVersionsClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.DeleteForUser(null, PackageType.Npm, "asd", 5));
+ await Assert.ThrowsAsync(() => client.DeleteForUser("", PackageType.Npm, "asd", 5));
+
+ await Assert.ThrowsAsync(() => client.DeleteForUser("owner", PackageType.Npm, null, 5));
+ await Assert.ThrowsAsync(() => client.DeleteForUser("owner", PackageType.Npm, "", 5));
+
+ await Assert.ThrowsAsync(() => client.DeleteForUser("owner", PackageType.Npm, "", 0));
+ }
+ }
+
+ public class TheRestoreForUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackageVersionsClient(connection);
+
+ await client.RestoreForUser("fake", PackageType.Npm, "name", 5);
+
+ connection.Received().Post(Arg.Is(u => u.ToString() == "/users/fake/packages/npm/name/versions/5/restore"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackageVersionsClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.RestoreForUser(null, PackageType.Npm, "asd", 5));
+ await Assert.ThrowsAsync(() => client.RestoreForUser("", PackageType.Npm, "asd", 5));
+
+ await Assert.ThrowsAsync(() => client.RestoreForUser("owner", PackageType.Npm, null, 5));
+ await Assert.ThrowsAsync(() => client.RestoreForUser("owner", PackageType.Npm, "", 5));
+
+ await Assert.ThrowsAsync(() => client.RestoreForUser("owner", PackageType.Npm, "", 0));
+ }
+ }
+ }
+}
diff --git a/Octokit.Tests/Clients/PackagesClientTests.cs b/Octokit.Tests/Clients/PackagesClientTests.cs
new file mode 100644
index 00000000..1b056c30
--- /dev/null
+++ b/Octokit.Tests/Clients/PackagesClientTests.cs
@@ -0,0 +1,344 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using NSubstitute;
+using Xunit;
+
+namespace Octokit.Tests.Clients
+{
+ public class PackagesClientTests
+ {
+ public class TheCtor
+ {
+ [Fact]
+ public void EnsuresNonNullArguments()
+ {
+ Assert.Throws(() => new PackagesClient(null));
+ }
+ }
+
+ public class TheGetAllForOrgMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.GetAllForOrg("fake", PackageType.RubyGems);
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "/orgs/fake/packages"), Arg.Is>(d => d.ContainsKey("package_type")));
+ }
+
+ [Fact]
+ public async Task RequestsCorrectUrlWithOptionalParameter()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.GetAllForOrg("fake", PackageType.RubyGems, PackageVisibility.Public);
+
+ var calls = connection.ReceivedCalls();
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "/orgs/fake/packages"), Arg.Is>(d => d.ContainsKey("package_type") && d.ContainsKey("visibility")));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await Assert.ThrowsAsync(() => client.GetAllForOrg(null, PackageType.Nuget));
+ await Assert.ThrowsAsync(() => client.GetAllForOrg("", PackageType.Nuget));
+ }
+ }
+
+ public class TheGetForOrgMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.GetForOrg("fake", PackageType.Npm, "name");
+
+ connection.Received().Get(Arg.Is(u => u.ToString() == "/orgs/fake/packages/npm/name"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackagesClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.GetForOrg(null, PackageType.Npm, "asd"));
+ await Assert.ThrowsAsync(() => client.GetForOrg("", PackageType.Npm, "asd"));
+
+ await Assert.ThrowsAsync(() => client.GetForOrg("owner", PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.GetForOrg("owner", PackageType.Npm, ""));
+ }
+ }
+
+ public class TheDeleteForOrgMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.DeleteForOrg("fake", PackageType.Npm, "name");
+
+ connection.Received().Delete(Arg.Is(u => u.ToString() == "/orgs/fake/packages/npm/name"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackagesClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.DeleteForOrg(null, PackageType.Npm, "asd"));
+ await Assert.ThrowsAsync(() => client.DeleteForOrg("", PackageType.Npm, "asd"));
+
+ await Assert.ThrowsAsync(() => client.DeleteForOrg("owner", PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.DeleteForOrg("owner", PackageType.Npm, ""));
+ }
+ }
+
+ public class TheRestoreForOrgMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.RestoreForOrg("fake", PackageType.Npm, "name");
+
+ connection.Received().Post(Arg.Is(u => u.ToString() == "/orgs/fake/packages/npm/name/restore"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackagesClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.RestoreForOrg(null, PackageType.Npm, "asd"));
+ await Assert.ThrowsAsync(() => client.RestoreForOrg("", PackageType.Npm, "asd"));
+
+ await Assert.ThrowsAsync(() => client.RestoreForOrg("owner", PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.RestoreForOrg("owner", PackageType.Npm, ""));
+ }
+ }
+
+ public class TheGetAllForActiveUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.GetAllForActiveUser(PackageType.RubyGems);
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "/user/packages"), Arg.Is>(d => d.ContainsKey("package_type")));
+ }
+
+ [Fact]
+ public async Task RequestsCorrectUrlWithOptionalParameter()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.GetAllForActiveUser(PackageType.RubyGems, PackageVisibility.Public);
+
+ var calls = connection.ReceivedCalls();
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "/user/packages"), Arg.Is>(d => d.ContainsKey("package_type") && d.ContainsKey("visibility")));
+ }
+ }
+
+ public class TheGetForActiveUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.GetForActiveUser(PackageType.Npm, "name");
+
+ connection.Received().Get(Arg.Is(u => u.ToString() == "/user/packages/npm/name"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackagesClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.GetForActiveUser(PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.GetForActiveUser(PackageType.Npm, ""));
+ }
+ }
+
+ public class TheDeleteForActiveUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.DeleteForActiveUser(PackageType.Npm, "name");
+
+ connection.Received().Delete(Arg.Is(u => u.ToString() == "/user/packages/npm/name"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackagesClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.DeleteForActiveUser(PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.DeleteForActiveUser(PackageType.Npm, ""));
+ }
+ }
+
+ public class TheRestoreForActiveUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.RestoreForActiveUser(PackageType.Npm, "name");
+
+ connection.Received().Post(Arg.Is(u => u.ToString() == "/user/packages/npm/name/restore"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackagesClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.RestoreForActiveUser(PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.RestoreForActiveUser(PackageType.Npm, ""));
+ }
+ }
+
+ public class TheGetAllForUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.GetAllForUser("fake", PackageType.RubyGems);
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "/users/fake/packages"), Arg.Is>(d => d.ContainsKey("package_type")));
+ }
+
+ [Fact]
+ public async Task RequestsCorrectUrlWithOptionalParameter()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.GetAllForUser("fake", PackageType.RubyGems, PackageVisibility.Public);
+
+ var calls = connection.ReceivedCalls();
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "/users/fake/packages"), Arg.Is>(d => d.ContainsKey("package_type") && d.ContainsKey("visibility")));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await Assert.ThrowsAsync(() => client.GetAllForUser(null, PackageType.Nuget));
+ await Assert.ThrowsAsync(() => client.GetAllForUser("", PackageType.Nuget));
+ }
+ }
+
+ public class TheGetForUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.GetForUser("fake", PackageType.Npm, "name");
+
+ connection.Received().Get(Arg.Is(u => u.ToString() == "/users/fake/packages/npm/name"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackagesClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.GetForUser(null, PackageType.Npm, "asd"));
+ await Assert.ThrowsAsync(() => client.GetForUser("", PackageType.Npm, "asd"));
+
+ await Assert.ThrowsAsync(() => client.GetForUser("owner", PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.GetForUser("owner", PackageType.Npm, ""));
+ }
+ }
+
+ public class TheDeleteForUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.DeleteForUser("fake", PackageType.Npm, "name");
+
+ connection.Received().Delete(Arg.Is(u => u.ToString() == "/users/fake/packages/npm/name"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackagesClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.DeleteForUser(null, PackageType.Npm, "asd"));
+ await Assert.ThrowsAsync(() => client.DeleteForUser("", PackageType.Npm, "asd"));
+
+ await Assert.ThrowsAsync(() => client.DeleteForUser("owner", PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.DeleteForUser("owner", PackageType.Npm, ""));
+ }
+ }
+
+ public class TheRestoreForUserMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PackagesClient(connection);
+
+ await client.RestoreForUser("fake", PackageType.Npm, "name");
+
+ connection.Received().Post(Arg.Is(u => u.ToString() == "/users/fake/packages/npm/name/restore"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new PackagesClient(Substitute.For());
+
+ await Assert.ThrowsAsync(() => client.RestoreForUser(null, PackageType.Npm, "asd"));
+ await Assert.ThrowsAsync(() => client.RestoreForUser("", PackageType.Npm, "asd"));
+
+ await Assert.ThrowsAsync(() => client.RestoreForUser("owner", PackageType.Npm, null));
+ await Assert.ThrowsAsync(() => client.RestoreForUser("owner", PackageType.Npm, ""));
+ }
+ }
+
+ }
+}
diff --git a/Octokit.Tests/Reactive/ObservablePackageVersionsTests.cs b/Octokit.Tests/Reactive/ObservablePackageVersionsTests.cs
new file mode 100644
index 00000000..0ba5cc33
--- /dev/null
+++ b/Octokit.Tests/Reactive/ObservablePackageVersionsTests.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Collections.Generic;
+using NSubstitute;
+using Octokit.Reactive;
+using Xunit;
+
+namespace Octokit.Tests.Reactive
+{
+ public class ObservablePackageVersionsTests
+ {
+ public class TheCtor
+ {
+ [Fact]
+ public void EnsuresNonNullArguments()
+ {
+ Assert.Throws(() => new ObservablePackageVersionsClient(null));
+ }
+ }
+
+ public class TheGetAllMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var gitHubClient = Substitute.For