Skip to content

Commit

Permalink
added remove link to the curated feed management page
Browse files Browse the repository at this point in the history
  • Loading branch information
half-ogre committed Mar 20, 2012
1 parent 1c7a82a commit 5390463
Show file tree
Hide file tree
Showing 13 changed files with 307 additions and 56 deletions.
14 changes: 7 additions & 7 deletions Facts/Commands/CreatedCuratedPackageCommandFacts.cs
Expand Up @@ -12,7 +12,7 @@ public class TheExecuteMethod
[Fact] [Fact]
public void WillThrowWhenCuratedFeedDoesNotExist() public void WillThrowWhenCuratedFeedDoesNotExist()
{ {
var cmd = new TestableCreatedCuratedPackageCommand(); var cmd = new TestableCreateCuratedPackageCommand();
cmd.StubCuratedFeedByKeyQry cmd.StubCuratedFeedByKeyQry
.Setup(stub => stub.Execute(It.IsAny<int>(), It.IsAny<bool>())) .Setup(stub => stub.Execute(It.IsAny<int>(), It.IsAny<bool>()))
.Returns((CuratedFeed)null); .Returns((CuratedFeed)null);
Expand All @@ -25,7 +25,7 @@ public void WillThrowWhenCuratedFeedDoesNotExist()
[Fact] [Fact]
public void WillThrowWhenPackageRegistrationDoesNotExist() public void WillThrowWhenPackageRegistrationDoesNotExist()
{ {
var cmd = new TestableCreatedCuratedPackageCommand(); var cmd = new TestableCreateCuratedPackageCommand();
cmd.StubPackageRegistrationByKeyQuery cmd.StubPackageRegistrationByKeyQuery
.Setup(stub => stub.Execute(It.IsAny<int>(), It.IsAny<bool>())) .Setup(stub => stub.Execute(It.IsAny<int>(), It.IsAny<bool>()))
.Returns((PackageRegistration)null); .Returns((PackageRegistration)null);
Expand All @@ -38,7 +38,7 @@ public void WillThrowWhenPackageRegistrationDoesNotExist()
[Fact] [Fact]
public void WillAddANewCuratedPackageToTheCuratedFeed() public void WillAddANewCuratedPackageToTheCuratedFeed()
{ {
var cmd = new TestableCreatedCuratedPackageCommand(); var cmd = new TestableCreateCuratedPackageCommand();
cmd.StubPackageRegistration.Key = 1066; cmd.StubPackageRegistration.Key = 1066;


cmd.Execute( cmd.Execute(
Expand All @@ -59,7 +59,7 @@ public void WillAddANewCuratedPackageToTheCuratedFeed()
[Fact] [Fact]
public void WillSaveTheEntityChanges() public void WillSaveTheEntityChanges()
{ {
var cmd = new TestableCreatedCuratedPackageCommand(); var cmd = new TestableCreateCuratedPackageCommand();


cmd.Execute( cmd.Execute(
0, 0,
Expand All @@ -71,7 +71,7 @@ public void WillSaveTheEntityChanges()
[Fact] [Fact]
public void WillReturnTheCreatedCuratedPackage() public void WillReturnTheCreatedCuratedPackage()
{ {
var cmd = new TestableCreatedCuratedPackageCommand(); var cmd = new TestableCreateCuratedPackageCommand();
cmd.StubPackageRegistration.Key = 1066; cmd.StubPackageRegistration.Key = 1066;


var curatedPackage = cmd.Execute( var curatedPackage = cmd.Execute(
Expand All @@ -89,9 +89,9 @@ public void WillReturnTheCreatedCuratedPackage()
} }
} }


public class TestableCreatedCuratedPackageCommand : CreatedCuratedPackageCommand public class TestableCreateCuratedPackageCommand : CreateCuratedPackageCommand
{ {
public TestableCreatedCuratedPackageCommand() public TestableCreateCuratedPackageCommand()
: base(null) : base(null)
{ {
StubCuratedFeed = new CuratedFeed { Key = 0, Name = "aName", }; StubCuratedFeed = new CuratedFeed { Key = 0, Name = "aName", };
Expand Down
86 changes: 86 additions & 0 deletions Facts/Commands/DeleteCuratedPackageCommandFacts.cs
@@ -0,0 +1,86 @@
using System;
using Moq;
using Xunit;
using System.Data.Entity;

namespace NuGetGallery.Commands
{
public class DeleteCuratedPackageCommandFacts
{
public class TheExecuteMethod
{
[Fact]
public void WillThrowWhenCuratedFeedDoesNotExist()
{
var cmd = new TestableDeleteCuratedPackageCommand();
cmd.StubCuratedFeedByKeyQry
.Setup(stub => stub.Execute(It.IsAny<int>(), It.IsAny<bool>()))
.Returns((CuratedFeed)null);

Assert.Throws<InvalidOperationException>(() => cmd.Execute(
42,
0));
}

[Fact]
public void WillThrowWhenCuratedPackageDoesNotExist()
{
var cmd = new TestableDeleteCuratedPackageCommand();
cmd.StubCuratedFeed.Packages = new[] { new CuratedPackage() { Key = 0 } };

Assert.Throws<InvalidOperationException>(() => cmd.Execute(
0,
1066));
}

[Fact]
public void WillDeleteTheCuratedPackage()
{
var cmd = new TestableDeleteCuratedPackageCommand();
var stubCuratedPackage = new CuratedPackage { Key = 1066 };
cmd.StubCuratedFeed.Packages = new[] { stubCuratedPackage };

cmd.Execute(
0,
1066);

cmd.StubCuratedPackageDbSet.Verify(stub => stub.Remove(stubCuratedPackage));
cmd.StubEntitiesContext.Verify(stub => stub.SaveChanges());
}
}

public class TestableDeleteCuratedPackageCommand : DeleteCuratedPackageCommand
{
public TestableDeleteCuratedPackageCommand()
: base(null)
{
StubCuratedFeed = new CuratedFeed { Key = 0, Name = "aName", };
StubCuratedPackageDbSet = new Mock<IDbSet<CuratedPackage>>();
StubCuratedFeedByKeyQry = new Mock<ICuratedFeedByKeyQuery>();
StubEntitiesContext = new Mock<IEntitiesContext>();

StubCuratedFeedByKeyQry
.Setup(stub => stub.Execute(It.IsAny<int>(), It.IsAny<bool>()))
.Returns(StubCuratedFeed);
StubEntitiesContext
.Setup(stub => stub.CuratedPackages)
.Returns(StubCuratedPackageDbSet.Object);

Entities = StubEntitiesContext.Object;
}

public CuratedFeed StubCuratedFeed { get; set; }
public Mock<IDbSet<CuratedPackage>> StubCuratedPackageDbSet { get; private set; }
public Mock<ICuratedFeedByKeyQuery> StubCuratedFeedByKeyQry { get; set; }
public Mock<IEntitiesContext> StubEntitiesContext { get; private set; }

protected override T GetService<T>()
{
if (typeof(T) == typeof(ICuratedFeedByKeyQuery))
return (T)StubCuratedFeedByKeyQry.Object;

throw new Exception("Tried to get unexpected service");
}
}
}
}
109 changes: 94 additions & 15 deletions Facts/Controllers/CuratedPackagesControllerFacts.cs
Expand Up @@ -17,7 +17,7 @@ public void WillReturn404IfTheCuratedFeedDoesNotExist()
var controller = new TestableCuratedPackagesController(); var controller = new TestableCuratedPackagesController();
controller.StubCuratedFeedByNameQry.Setup(stub => stub.Execute(It.IsAny<string>(), It.IsAny<bool>())).Returns((CuratedFeed)null); controller.StubCuratedFeedByNameQry.Setup(stub => stub.Execute(It.IsAny<string>(), It.IsAny<bool>())).Returns((CuratedFeed)null);


var result = controller.CreateCuratedPackageForm("aFeedName"); var result = controller.GetCreateCuratedPackageForm("aFeedName");


Assert.IsType<HttpNotFoundResult>(result); Assert.IsType<HttpNotFoundResult>(result);
} }
Expand All @@ -28,7 +28,7 @@ public void WillReturn403IfTheCurrentUsersIsNotAManagerOfTheCuratedFeed()
var controller = new TestableCuratedPackagesController(); var controller = new TestableCuratedPackagesController();
controller.StubIdentity.Setup(stub => stub.Name).Returns("notAManager"); controller.StubIdentity.Setup(stub => stub.Name).Returns("notAManager");


var result = controller.CreateCuratedPackageForm("aFeedName") as HttpStatusCodeResult; var result = controller.GetCreateCuratedPackageForm("aFeedName") as HttpStatusCodeResult;


Assert.NotNull(result); Assert.NotNull(result);
Assert.Equal(403, result.StatusCode); Assert.Equal(403, result.StatusCode);
Expand All @@ -40,7 +40,7 @@ public void WillPushTheCuratedFeedNameIntoTheViewBag()
var controller = new TestableCuratedPackagesController(); var controller = new TestableCuratedPackagesController();
controller.StubCuratedFeed.Name = "theCuratedFeedName"; controller.StubCuratedFeed.Name = "theCuratedFeedName";


var result = controller.CreateCuratedPackageForm("aFeedName") as ViewResult; var result = controller.GetCreateCuratedPackageForm("aFeedName") as ViewResult;


Assert.NotNull(result); Assert.NotNull(result);
Assert.Equal("theCuratedFeedName", result.ViewBag.CuratedFeedName); Assert.Equal("theCuratedFeedName", result.ViewBag.CuratedFeedName);
Expand All @@ -65,7 +65,7 @@ public void WillReturn404IfTheCuratedFeedDoesNotExist()
var controller = new TestableCuratedPackagesController(); var controller = new TestableCuratedPackagesController();
controller.StubCuratedFeedByNameQry.Setup(stub => stub.Execute(It.IsAny<string>(), It.IsAny<bool>())).Returns((CuratedFeed)null); controller.StubCuratedFeedByNameQry.Setup(stub => stub.Execute(It.IsAny<string>(), It.IsAny<bool>())).Returns((CuratedFeed)null);


var result = controller.CuratedPackages("aFeedName", new CreatedCuratedPackageRequest()); var result = controller.PostCuratedPackages("aFeedName", new CreateCuratedPackageRequest());


Assert.IsType<HttpNotFoundResult>(result); Assert.IsType<HttpNotFoundResult>(result);
} }
Expand All @@ -76,7 +76,7 @@ public void WillReturn403IfTheCurrentUsersIsNotAManagerOfTheCuratedFeed()
var controller = new TestableCuratedPackagesController(); var controller = new TestableCuratedPackagesController();
controller.StubIdentity.Setup(stub => stub.Name).Returns("notAManager"); controller.StubIdentity.Setup(stub => stub.Name).Returns("notAManager");


var result = controller.CuratedPackages("aFeedName", new CreatedCuratedPackageRequest()) as HttpStatusCodeResult; var result = controller.PostCuratedPackages("aFeedName", new CreateCuratedPackageRequest()) as HttpStatusCodeResult;


Assert.NotNull(result); Assert.NotNull(result);
Assert.Equal(403, result.StatusCode); Assert.Equal(403, result.StatusCode);
Expand All @@ -89,7 +89,7 @@ public void WillPushTheCuratedFeedNameIntoTheViewBagAndShowTheCreateCuratedPacka
controller.StubCuratedFeed.Name = "theCuratedFeedName"; controller.StubCuratedFeed.Name = "theCuratedFeedName";
controller.ModelState.AddModelError("", "anError"); controller.ModelState.AddModelError("", "anError");


var result = controller.CuratedPackages("aFeedName", new CreatedCuratedPackageRequest()) as ViewResult; var result = controller.PostCuratedPackages("aFeedName", new CreateCuratedPackageRequest()) as ViewResult;


Assert.NotNull(result); Assert.NotNull(result);
Assert.Equal("theCuratedFeedName", result.ViewBag.CuratedFeedName); Assert.Equal("theCuratedFeedName", result.ViewBag.CuratedFeedName);
Expand All @@ -103,7 +103,7 @@ public void WillPushTheCuratedFeedNameIntoTheViewBagAndShowTheCreateCuratedPacka
controller.StubCuratedFeed.Name = "theCuratedFeedName"; controller.StubCuratedFeed.Name = "theCuratedFeedName";
controller.StubPackageRegistrationByIdQry.Setup(stub => stub.Execute(It.IsAny<string>(), It.IsAny<bool>())).Returns((PackageRegistration)null); controller.StubPackageRegistrationByIdQry.Setup(stub => stub.Execute(It.IsAny<string>(), It.IsAny<bool>())).Returns((PackageRegistration)null);


var result = controller.CuratedPackages("aFeedName", new CreatedCuratedPackageRequest()) as ViewResult; var result = controller.PostCuratedPackages("aFeedName", new CreateCuratedPackageRequest()) as ViewResult;


Assert.NotNull(result); Assert.NotNull(result);
Assert.Equal("theCuratedFeedName", result.ViewBag.CuratedFeedName); Assert.Equal("theCuratedFeedName", result.ViewBag.CuratedFeedName);
Expand All @@ -118,9 +118,9 @@ public void WillCreateTheCuratedPackage()
controller.StubCuratedFeed.Key = 42; controller.StubCuratedFeed.Key = 42;
controller.StubPackageRegistration.Key = 1066; controller.StubPackageRegistration.Key = 1066;


controller.CuratedPackages( controller.PostCuratedPackages(
"aFeedName", "aFeedName",
new CreatedCuratedPackageRequest new CreateCuratedPackageRequest
{ {
PackageId = "thePackageId", Notes = "theNotes" PackageId = "thePackageId", Notes = "theNotes"
}); });
Expand All @@ -138,7 +138,7 @@ public void WillRedirectToTheCuratedFeedRouteAfterCreatingTheCuratedPackage()
{ {
var controller = new TestableCuratedPackagesController(); var controller = new TestableCuratedPackagesController();


var result = controller.CuratedPackages("aFeedName", new CreatedCuratedPackageRequest()) as RedirectToRouteResult; var result = controller.PostCuratedPackages("aFeedName", new CreateCuratedPackageRequest()) as RedirectToRouteResult;


Assert.NotNull(result); Assert.NotNull(result);
Assert.Equal(RouteName.CuratedFeed, result.RouteName); Assert.Equal(RouteName.CuratedFeed, result.RouteName);
Expand Down Expand Up @@ -166,7 +166,7 @@ public void WillReturn404IfTheCuratedFeedDoesNotExist()
var controller = new TestableCuratedPackagesController(); var controller = new TestableCuratedPackagesController();
controller.StubCuratedFeedByNameQry.Setup(stub => stub.Execute(It.IsAny<string>(), It.IsAny<bool>())).Returns((CuratedFeed)null); controller.StubCuratedFeedByNameQry.Setup(stub => stub.Execute(It.IsAny<string>(), It.IsAny<bool>())).Returns((CuratedFeed)null);


var result = controller.CuratedPackage("aCuratedFeedName", "aCuratedPackageId", new ModifyCuratedPackageRequest()); var result = controller.PatchCuratedPackage("aCuratedFeedName", "aCuratedPackageId", new ModifyCuratedPackageRequest());


Assert.IsType<HttpNotFoundResult>(result); Assert.IsType<HttpNotFoundResult>(result);
} }
Expand All @@ -177,7 +177,7 @@ public void WillReturn404IfTheCuratedPackageDoesNotExist()
var controller = new TestableCuratedPackagesController(); var controller = new TestableCuratedPackagesController();
controller.StubCuratedFeed.Packages = new[] { new CuratedPackage { PackageRegistration = new PackageRegistration() } }; controller.StubCuratedFeed.Packages = new[] { new CuratedPackage { PackageRegistration = new PackageRegistration() } };


var result = controller.CuratedPackage("aCuratedFeedName", "aCuratedPackageId", new ModifyCuratedPackageRequest()); var result = controller.PatchCuratedPackage("aCuratedFeedName", "aCuratedPackageId", new ModifyCuratedPackageRequest());


Assert.IsType<HttpNotFoundResult>(result); Assert.IsType<HttpNotFoundResult>(result);
} }
Expand All @@ -188,7 +188,7 @@ public void WillReturn403IfTheCuratedPackageDoesNotExist()
var controller = new TestableCuratedPackagesController(); var controller = new TestableCuratedPackagesController();
controller.StubCuratedFeed.Managers = new[] {new User {Username = "notAManager"}}; controller.StubCuratedFeed.Managers = new[] {new User {Username = "notAManager"}};


var result = controller.CuratedPackage("aCuratedFeedName", "aCuratedPackageId", new ModifyCuratedPackageRequest()) as HttpStatusCodeResult; var result = controller.PatchCuratedPackage("aCuratedFeedName", "aCuratedPackageId", new ModifyCuratedPackageRequest()) as HttpStatusCodeResult;


Assert.NotNull(result); Assert.NotNull(result);
Assert.Equal(403, result.StatusCode); Assert.Equal(403, result.StatusCode);
Expand All @@ -200,7 +200,7 @@ public void WillReturn400IfTheModelStateIsInvalid()
var controller = new TestableCuratedPackagesController(); var controller = new TestableCuratedPackagesController();
controller.ModelState.AddModelError("", "anError"); controller.ModelState.AddModelError("", "anError");


var result = controller.CuratedPackage("aCuratedFeedName", "aCuratedPackageId", new ModifyCuratedPackageRequest()) as HttpStatusCodeResult; var result = controller.PatchCuratedPackage("aCuratedFeedName", "aCuratedPackageId", new ModifyCuratedPackageRequest()) as HttpStatusCodeResult;


Assert.NotNull(result); Assert.NotNull(result);
Assert.Equal(400, result.StatusCode); Assert.Equal(400, result.StatusCode);
Expand All @@ -213,7 +213,7 @@ public void WillModifyTheCuratedPackageWhenRequestIsValid()
controller.StubCuratedFeed.Key = 42; controller.StubCuratedFeed.Key = 42;
controller.StubCuratedFeed.Packages = new[] { new CuratedPackage { Key = 1066, PackageRegistration = new PackageRegistration { Id = "theCuratedPackageId" } } }; controller.StubCuratedFeed.Packages = new[] { new CuratedPackage { Key = 1066, PackageRegistration = new PackageRegistration { Id = "theCuratedPackageId" } } };


controller.CuratedPackage("theCuratedFeedName", "theCuratedPackageId", new ModifyCuratedPackageRequest{ Included = true}); controller.PatchCuratedPackage("theCuratedFeedName", "theCuratedPackageId", new ModifyCuratedPackageRequest{ Included = true});


controller.StubModifyCuratedPackageCommand.Verify(stub => stub.Execute( controller.StubModifyCuratedPackageCommand.Verify(stub => stub.Execute(
42, 42,
Expand All @@ -234,13 +234,88 @@ public TestableCuratedPackagesController()
} }
} }


public class TheDeleteCuratedPackageAction
{
[Fact]
public void WillReturn404IfTheCuratedFeedDoesNotExist()
{
var controller = new TestableCuratedPackagesController();
controller.StubCuratedFeedByNameQry.Setup(stub => stub.Execute(It.IsAny<string>(), It.IsAny<bool>())).Returns((CuratedFeed)null);

var result = controller.DeleteCuratedPackage("aCuratedFeedName", "aCuratedPackageId");

Assert.IsType<HttpNotFoundResult>(result);
}

[Fact]
public void WillReturn404IfTheCuratedPackageDoesNotExist()
{
var controller = new TestableCuratedPackagesController();
controller.StubCuratedFeed.Packages = new[] { new CuratedPackage { PackageRegistration = new PackageRegistration() } };

var result = controller.DeleteCuratedPackage("aCuratedFeedName", "aCuratedPackageId");

Assert.IsType<HttpNotFoundResult>(result);
}

[Fact]
public void WillReturn403IfTheCuratedPackageDoesNotExist()
{
var controller = new TestableCuratedPackagesController();
controller.StubCuratedFeed.Managers = new[] { new User { Username = "notAManager" } };

var result = controller.DeleteCuratedPackage("aCuratedFeedName", "aCuratedPackageId") as HttpStatusCodeResult;

Assert.NotNull(result);
Assert.Equal(403, result.StatusCode);
}

[Fact]
public void WillDeleteTheCuratedPackageWhenRequestIsValid()
{
var controller = new TestableCuratedPackagesController();
controller.StubCuratedFeed.Key = 42;
controller.StubCuratedFeed.Packages = new[] { new CuratedPackage { Key = 1066, PackageRegistration = new PackageRegistration { Id = "theCuratedPackageId" } } };

controller.DeleteCuratedPackage("theCuratedFeedName", "theCuratedPackageId");

controller.StubDeleteCuratedPackageCommand.Verify(stub => stub.Execute(
42,
1066));
}

[Fact]
public void WillReturn204AfterDeletingTheCuratedPackage()
{
var controller = new TestableCuratedPackagesController();

var result = controller.DeleteCuratedPackage("aCuratedFeedName", "aCuratedPackageId") as HttpStatusCodeResult;

Assert.NotNull(result);
Assert.Equal(204, result.StatusCode);
}

public class TestableCuratedPackagesController : TestableCuratedPackagesControllerBase
{
public TestableCuratedPackagesController()
{
StubCuratedFeed.Managers = new[] { new User { Username = "aUsername" } };
StubCuratedFeed.Packages = new[] { new CuratedPackage { PackageRegistration = new PackageRegistration { Id = "aCuratedPackageId" } } };
StubCuratedFeedByNameQry
.Setup(stub => stub.Execute(It.IsAny<string>(), It.IsAny<bool>()))
.Returns(StubCuratedFeed);
}
}
}

public abstract class TestableCuratedPackagesControllerBase : CuratedPackagesController public abstract class TestableCuratedPackagesControllerBase : CuratedPackagesController
{ {
protected TestableCuratedPackagesControllerBase() protected TestableCuratedPackagesControllerBase()
{ {
StubCreatedCuratedPackageCmd = new Mock<ICreatedCuratedPackageCommand>(); StubCreatedCuratedPackageCmd = new Mock<ICreatedCuratedPackageCommand>();
StubCuratedFeed = new CuratedFeed { Key = 0, Name = "aName", Managers = new HashSet<User>( new []{ new User { Username = "aUsername" } }) }; StubCuratedFeed = new CuratedFeed { Key = 0, Name = "aName", Managers = new HashSet<User>( new []{ new User { Username = "aUsername" } }) };
StubCuratedFeedByNameQry = new Mock<ICuratedFeedByNameQuery>(); StubCuratedFeedByNameQry = new Mock<ICuratedFeedByNameQuery>();
StubDeleteCuratedPackageCommand = new Mock<IDeleteCuratedPackageCommand>();
StubIdentity = new Mock<IIdentity>(); StubIdentity = new Mock<IIdentity>();
StubModifyCuratedPackageCommand = new Mock<IModifyCuratedPackageCommand>(); StubModifyCuratedPackageCommand = new Mock<IModifyCuratedPackageCommand>();
StubPackageRegistration = new PackageRegistration { Key = 0, Id = "anId" }; StubPackageRegistration = new PackageRegistration { Key = 0, Id = "anId" };
Expand All @@ -253,6 +328,7 @@ protected TestableCuratedPackagesControllerBase()
public Mock<ICreatedCuratedPackageCommand> StubCreatedCuratedPackageCmd { get; set; } public Mock<ICreatedCuratedPackageCommand> StubCreatedCuratedPackageCmd { get; set; }
public CuratedFeed StubCuratedFeed { get; set; } public CuratedFeed StubCuratedFeed { get; set; }
public Mock<ICuratedFeedByNameQuery> StubCuratedFeedByNameQry { get; private set; } public Mock<ICuratedFeedByNameQuery> StubCuratedFeedByNameQry { get; private set; }
public Mock<IDeleteCuratedPackageCommand> StubDeleteCuratedPackageCommand { get; private set; }
public Mock<IIdentity> StubIdentity { get; private set; } public Mock<IIdentity> StubIdentity { get; private set; }
public Mock<IModifyCuratedPackageCommand> StubModifyCuratedPackageCommand { get; private set; } public Mock<IModifyCuratedPackageCommand> StubModifyCuratedPackageCommand { get; private set; }
public PackageRegistration StubPackageRegistration { get; private set; } public PackageRegistration StubPackageRegistration { get; private set; }
Expand All @@ -271,6 +347,9 @@ protected override T GetService<T>()
if (typeof(T) == typeof(ICuratedFeedByNameQuery)) if (typeof(T) == typeof(ICuratedFeedByNameQuery))
return (T)StubCuratedFeedByNameQry.Object; return (T)StubCuratedFeedByNameQry.Object;


if (typeof(T) == typeof(IDeleteCuratedPackageCommand))
return (T)StubDeleteCuratedPackageCommand.Object;

if (typeof(T) == typeof(IModifyCuratedPackageCommand)) if (typeof(T) == typeof(IModifyCuratedPackageCommand))
return (T)StubModifyCuratedPackageCommand.Object; return (T)StubModifyCuratedPackageCommand.Object;


Expand Down

0 comments on commit 5390463

Please sign in to comment.