Stylet/StyletUnitTests/ConductorNavigatingTests.cs

304 lines
10 KiB
C#

using Moq;
using Moq.Protected;
using NUnit.Framework;
using Stylet;
using System;
using System.Threading.Tasks;
namespace StyletUnitTests
{
[TestFixture]
public class ConductorNavigatingTests
{
public interface IMyScreen : IScreen, IDisposable
{ }
private class MyConductor : Conductor<IScreen>.StackNavigation
{
public bool CanCloseValue = true;
public override async Task<bool> CanCloseAsync()
{
return this.CanCloseValue && await base.CanCloseAsync();
}
}
private MyConductor conductor;
[SetUp]
public void SetUp()
{
this.conductor = new MyConductor();
}
[Test]
public void ActiveItemIsNullBeforeAnyItemsActivated()
{
Assert.IsNull(this.conductor.ActiveItem);
Assert.That(this.conductor.GetChildren(), Is.EquivalentTo(new IScreen[] { null }));
}
[Test]
public void InitialActivateSetsItemAsActiveItem()
{
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
Assert.AreEqual(screen.Object, this.conductor.ActiveItem);
}
[Test]
public void InitialActivateDoesNotActivateItemIfConductorIsNotActive()
{
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
screen.Verify(x => x.Activate(), Times.Never);
}
[Test]
public void InitialActivateActivatesItemIfConductorIsActive()
{
((IScreenState)this.conductor).Activate();
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
screen.Verify(x => x.Activate());
}
[Test]
public void InitialActivateDeactivatesItemIfConductorIsDeactivated()
{
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
screen.Verify(x => x.Deactivate());
}
[Test]
public void ActivatesActiveItemWhenActivated()
{
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
screen.Verify(x => x.Activate(), Times.Never);
((IScreenState)this.conductor).Activate();
screen.Verify(x => x.Activate());
}
[Test]
public void DeactivatesActiveItemWhenDeactivated()
{
((IScreenState)this.conductor).Activate();
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
((IScreenState)this.conductor).Deactivate();
screen.Verify(x => x.Deactivate());
}
[Test]
public void ActivateDeactivatesPreviousItemIfConductorIsActiveAndPreviousItemCanClose()
{
var screen1 = new Mock<IScreen>();
var screen2 = new Mock<IScreen>();
((IScreenState)this.conductor).Activate();
this.conductor.ActivateItem(screen1.Object);
screen1.Setup(x => x.CanCloseAsync()).Returns(Task.FromResult(true));
this.conductor.ActivateItem(screen2.Object);
screen1.Verify(x => x.Deactivate());
}
[Test]
public void ActivatingCurrentScreenReactivatesScreen()
{
var screen = new Mock<IMyScreen>();
((IScreenState)this.conductor).Activate();
this.conductor.ActivateItem(screen.Object);
this.conductor.ActivateItem(screen.Object);
screen.Verify(x => x.Activate(), Times.Exactly(2));
screen.Verify(x => x.Close(), Times.Never);
screen.Verify(x => x.Dispose(), Times.Never);
}
[Test]
public void CloseItemDoesNothingIfToldToDeactiveInactiveItem()
{
var screen1 = new Mock<IMyScreen>();
var screen2 = new Mock<IMyScreen>();
((IScreenState)this.conductor).Activate();
this.conductor.ActivateItem(screen1.Object);
this.conductor.CloseItem(screen2.Object);
screen1.Verify(x => x.Close(), Times.Never);
screen1.Verify(x => x.Dispose(), Times.Never);
screen2.Verify(x => x.Activate(), Times.Never);
}
[Test]
public void DeactiveDoesNotChangeActiveItem()
{
var screen = new Mock<IScreen>();
((IScreenState)this.conductor).Activate();
this.conductor.ActivateItem(screen.Object);
this.conductor.DeactivateItem(screen.Object);
screen.Verify(x => x.Deactivate());
Assert.AreEqual(this.conductor.ActiveItem, screen.Object);
}
[Test]
public void ActivateSetsConductorAsItemsParent()
{
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
screen.VerifySet(x => x.Parent = this.conductor);
}
[Test]
public void SettingActiveItemActivatesItem()
{
var screen = new Mock<IScreen>();
((IScreenState)this.conductor).Activate();
this.conductor.ActiveItem =screen.Object;
screen.Verify(x => x.Activate());
Assert.AreEqual(this.conductor.ActiveItem, screen.Object);
}
[Test]
public void CloseClosesAndRemovesItemsParent()
{
var screen = new Mock<IScreen>();
screen.Setup(x => x.CanCloseAsync()).Returns(Task.FromResult(true));
screen.Setup(x => x.Parent).Returns(this.conductor);
this.conductor.ActivateItem(screen.Object);
this.conductor.CloseItem(screen.Object);
screen.Verify(x => x.Close());
screen.VerifySet(x => x.Parent = null);
}
[Test]
public void CloseDisposesItemIfDisposeChildrenIsTrue()
{
var screen = new Mock<IMyScreen>();
screen.Setup(x => x.CanCloseAsync()).Returns(Task.FromResult(true));
this.conductor.ActivateItem(screen.Object);
this.conductor.CloseItem(screen.Object);
screen.Verify(x => x.Dispose());
}
[Test]
public void CloseDoesNotDisposeItemIfDisposeChildrenIsFalse()
{
var screen = new Mock<IMyScreen>();
screen.Setup(x => x.CanCloseAsync()).Returns(Task.FromResult(true));
this.conductor.DisposeChildren = false;
this.conductor.ActivateItem(screen.Object);
this.conductor.CloseItem(screen.Object);
screen.Verify(x => x.Dispose(), Times.Never);
}
[Test]
public void CanCloseReturnsTrueIfNoActiveItem()
{
Assert.IsTrue(this.conductor.CanCloseAsync().Result);
}
[Test]
public void CanCloseReturnsAllItemsCanClose()
{
var screen1 = new Mock<IScreen>();
var screen2 = new Mock<IScreen>();
this.conductor.ActivateItem(screen1.Object);
this.conductor.ActivateItem(screen2.Object);
screen1.Setup(x => x.CanCloseAsync()).Returns(Task.FromResult(true));
screen2.Setup(x => x.CanCloseAsync()).Returns(Task.FromResult(false));
Assert.IsFalse(this.conductor.CanCloseAsync().Result);
}
[Test]
public void ConductorCanCloseAsyncCallsCanCloseOnSelfBeforeChildren()
{
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
this.conductor.CanCloseValue = false;
Assert.IsFalse(this.conductor.CanCloseAsync().Result);
screen.Verify(x => x.CanCloseAsync(), Times.Never());
}
[Test]
public void DeactivatingActiveItemGoesBack()
{
((IScreenState)this.conductor).Activate();
var screen1 = new Mock<IScreen>();
var screen2 = new Mock<IScreen>();
this.conductor.ActivateItem(screen1.Object);
screen1.Verify(x => x.Activate());
this.conductor.ActivateItem(screen2.Object);
screen2.Verify(x => x.Activate());
this.conductor.DeactivateItem(screen2.Object);
screen2.Verify(x => x.Deactivate(), Times.Once);
screen1.Verify(x => x.Activate(), Times.Once);
}
[Test]
public void ClearClosesAllItemsExceptCurrent()
{
((IScreenState)this.conductor).Activate();
var screen1 = new Mock<IScreen>();
var screen2 = new Mock<IScreen>();
this.conductor.ActivateItem(screen1.Object);
this.conductor.ActivateItem(screen2.Object);
this.conductor.Clear();
Assert.AreEqual(screen2.Object, this.conductor.ActiveItem);
screen2.Setup(x => x.CanCloseAsync()).Returns(Task.FromResult(true));
this.conductor.GoBack();
Assert.IsNull(this.conductor.ActiveItem);
}
[Test]
public void CloseClosesAllItems()
{
var screen1 = new Mock<IMyScreen>();
screen1.SetupGet(x => x.Parent).Returns(this.conductor);
var screen2 = new Mock<IMyScreen>();
screen2.SetupGet(x => x.Parent).Returns(this.conductor);
this.conductor.ActivateItem(screen1.Object);
this.conductor.ActivateItem(screen2.Object);
((IScreenState)this.conductor).Close();
screen1.Verify(x => x.Close());
screen1.VerifySet(x => x.Parent = null);
screen2.Verify(x => x.Close());
screen2.VerifySet(x => x.Parent = null);
}
[Test]
public void ClosesItemIfItemRequestsClose()
{
var screen = new Mock<IMyScreen>();
this.conductor.ActivateItem(screen.Object);
screen.Setup(x => x.CanCloseAsync()).Returns(Task.FromResult(true));
((IChildDelegate)this.conductor).CloseItem(screen.Object);
screen.Verify(x => x.Close());
Assert.Null(this.conductor.ActiveItem);
}
[Test]
public void NestedActivateItemsResultsInLastActivatedItemActive()
{
var screen1 = new Mock<Screen>() { CallBase = true };
var screen2 = new Screen();
screen1.Protected().Setup("OnActivate").Callback(() => conductor.ActivateItem(screen2));
((IScreenState)this.conductor).Activate();
this.conductor.ActivateItem(screen1.Object);
Assert.AreEqual(screen2, this.conductor.ActiveItem);
}
}
}