|
|
@@ -18,7 +18,7 @@ public class SubViewTests
|
|
|
};
|
|
|
sub.SuperViewChanged += (s, e) =>
|
|
|
{
|
|
|
- if (e.SuperView is { })
|
|
|
+ if (sub.SuperView is { })
|
|
|
{
|
|
|
subRaisedCount++;
|
|
|
}
|
|
|
@@ -46,7 +46,7 @@ public class SubViewTests
|
|
|
};
|
|
|
sub.SuperViewChanged += (s, e) =>
|
|
|
{
|
|
|
- if (e.SuperView is null)
|
|
|
+ if (sub.SuperView is null)
|
|
|
{
|
|
|
subRaisedCount++;
|
|
|
}
|
|
|
@@ -393,23 +393,23 @@ public class SubViewTests
|
|
|
var superView = new View ();
|
|
|
|
|
|
int superViewChangedCount = 0;
|
|
|
- //int superViewChangingCount = 0;
|
|
|
+ int superViewChangingCount = 0;
|
|
|
|
|
|
view.SuperViewChanged += (s, e) =>
|
|
|
{
|
|
|
superViewChangedCount++;
|
|
|
};
|
|
|
|
|
|
- //view.SuperViewChanging += (s, e) =>
|
|
|
- //{
|
|
|
- // superViewChangingCount++;
|
|
|
- //};
|
|
|
+ view.SuperViewChanging += (s, e) =>
|
|
|
+ {
|
|
|
+ superViewChangingCount++;
|
|
|
+ };
|
|
|
|
|
|
// Act
|
|
|
superView.Add (view);
|
|
|
|
|
|
// Assert
|
|
|
- //Assert.Equal (1, superViewChangingCount);
|
|
|
+ Assert.Equal (1, superViewChangingCount);
|
|
|
Assert.Equal (1, superViewChangedCount);
|
|
|
|
|
|
}
|
|
|
@@ -692,4 +692,295 @@ public class SubViewTests
|
|
|
Assert.Single (removedViews);
|
|
|
Assert.Contains (subView2, removedViews);
|
|
|
}
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void SuperViewChanging_Raised_Before_SuperViewChanged ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ var superView = new View ();
|
|
|
+ var subView = new View ();
|
|
|
+
|
|
|
+ var events = new List<string> ();
|
|
|
+
|
|
|
+ subView.SuperViewChanging += (s, e) => { events.Add ("SuperViewChanging"); };
|
|
|
+
|
|
|
+ subView.SuperViewChanged += (s, e) => { events.Add ("SuperViewChanged"); };
|
|
|
+
|
|
|
+ // Act
|
|
|
+ superView.Add (subView);
|
|
|
+
|
|
|
+ // Assert
|
|
|
+ Assert.Equal (2, events.Count);
|
|
|
+ Assert.Equal ("SuperViewChanging", events [0]);
|
|
|
+ Assert.Equal ("SuperViewChanged", events [1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void SuperViewChanging_Provides_OldSuperView_On_Add ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ var superView = new View ();
|
|
|
+ var subView = new View ();
|
|
|
+
|
|
|
+ View? currentValueInEvent = new View (); // Set to non-null to ensure it gets updated
|
|
|
+ View? newValueInEvent = null;
|
|
|
+
|
|
|
+ subView.SuperViewChanging += (s, e) =>
|
|
|
+ {
|
|
|
+ currentValueInEvent = e.CurrentValue;
|
|
|
+ newValueInEvent = e.NewValue;
|
|
|
+ };
|
|
|
+
|
|
|
+ // Act
|
|
|
+ superView.Add (subView);
|
|
|
+
|
|
|
+ // Assert
|
|
|
+ Assert.Null (currentValueInEvent); // Was null before add
|
|
|
+ Assert.Equal (superView, newValueInEvent); // Will be superView after add
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void SuperViewChanging_Provides_OldSuperView_On_Remove ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ var superView = new View ();
|
|
|
+ var subView = new View ();
|
|
|
+
|
|
|
+ superView.Add (subView);
|
|
|
+
|
|
|
+ View? currentValueInEvent = null;
|
|
|
+ View? newValueInEvent = new View (); // Set to non-null to ensure it gets updated
|
|
|
+
|
|
|
+ subView.SuperViewChanging += (s, e) =>
|
|
|
+ {
|
|
|
+ currentValueInEvent = e.CurrentValue;
|
|
|
+ newValueInEvent = e.NewValue;
|
|
|
+ };
|
|
|
+
|
|
|
+ // Act
|
|
|
+ superView.Remove (subView);
|
|
|
+
|
|
|
+ // Assert
|
|
|
+ Assert.Equal (superView, currentValueInEvent); // Was superView before remove
|
|
|
+ Assert.Null (newValueInEvent); // Will be null after remove
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void SuperViewChanging_Allows_Access_To_App_Before_Remove ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ using IApplication app = Application.Create ();
|
|
|
+ var runnable = new Runnable<bool> ();
|
|
|
+ var subView = new View ();
|
|
|
+
|
|
|
+ runnable.Add (subView);
|
|
|
+ SessionToken? token = app.Begin (runnable);
|
|
|
+
|
|
|
+ IApplication? appInEvent = null;
|
|
|
+
|
|
|
+ subView.SuperViewChanging += (s, e) =>
|
|
|
+ {
|
|
|
+ Assert.NotNull (s);
|
|
|
+ // At this point, SuperView is still set, so App should be accessible
|
|
|
+ appInEvent = (s as View)?.App;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ Assert.NotNull (runnable.App);
|
|
|
+
|
|
|
+ // Act
|
|
|
+ runnable.Remove (subView);
|
|
|
+
|
|
|
+ // Assert
|
|
|
+ Assert.NotNull (appInEvent);
|
|
|
+ Assert.Equal (app, appInEvent);
|
|
|
+
|
|
|
+ app.End (token!);
|
|
|
+ runnable.Dispose ();
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void OnSuperViewChanging_Called_Before_OnSuperViewChanged ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ var superView = new View ();
|
|
|
+ var events = new List<string> ();
|
|
|
+
|
|
|
+ var subView = new TestViewWithSuperViewEvents (events);
|
|
|
+
|
|
|
+ // Act
|
|
|
+ superView.Add (subView);
|
|
|
+
|
|
|
+ // Assert
|
|
|
+ Assert.Equal (2, events.Count);
|
|
|
+ Assert.Equal ("OnSuperViewChanging", events [0]);
|
|
|
+ Assert.Equal ("OnSuperViewChanged", events [1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void SuperViewChanging_Raised_When_Changing_Between_SuperViews ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ var superView1 = new View ();
|
|
|
+ var superView2 = new View ();
|
|
|
+ var subView = new View ();
|
|
|
+
|
|
|
+ superView1.Add (subView);
|
|
|
+
|
|
|
+ View? currentValueInEvent = null;
|
|
|
+ View? newValueInEvent = null;
|
|
|
+
|
|
|
+ subView.SuperViewChanging += (s, e) =>
|
|
|
+ {
|
|
|
+ currentValueInEvent = e.CurrentValue;
|
|
|
+ newValueInEvent = e.NewValue;
|
|
|
+ };
|
|
|
+
|
|
|
+ // Act
|
|
|
+ superView2.Add (subView);
|
|
|
+
|
|
|
+ // Assert
|
|
|
+ Assert.Equal (superView1, currentValueInEvent);
|
|
|
+ Assert.Equal (superView2, newValueInEvent);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Helper class for testing virtual method calls
|
|
|
+ private class TestViewWithSuperViewEvents : View
|
|
|
+ {
|
|
|
+ private readonly List<string> _events;
|
|
|
+
|
|
|
+ public TestViewWithSuperViewEvents (List<string> events) { _events = events; }
|
|
|
+
|
|
|
+ protected override bool OnSuperViewChanging (ValueChangingEventArgs<View?> args)
|
|
|
+ {
|
|
|
+ _events.Add ("OnSuperViewChanging");
|
|
|
+ return base.OnSuperViewChanging (args);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void OnSuperViewChanged (ValueChangedEventArgs<View?> args)
|
|
|
+ {
|
|
|
+ _events.Add ("OnSuperViewChanged");
|
|
|
+ base.OnSuperViewChanged (args);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void SuperViewChanging_Can_Be_Cancelled_Via_Event ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ var superView = new View ();
|
|
|
+ var subView = new View ();
|
|
|
+
|
|
|
+ subView.SuperViewChanging += (s, e) =>
|
|
|
+ {
|
|
|
+ e.Handled = true; // Cancel the change
|
|
|
+ };
|
|
|
+
|
|
|
+ // Act
|
|
|
+ superView.Add (subView);
|
|
|
+
|
|
|
+ // Assert - SuperView should not be set because the change was cancelled
|
|
|
+ Assert.Null (subView.SuperView);
|
|
|
+ Assert.Empty (superView.SubViews);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void SuperViewChanging_Can_Be_Cancelled_Via_Virtual_Method ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ var superView = new View ();
|
|
|
+ var subView = new TestViewThatCancelsChange ();
|
|
|
+
|
|
|
+ // Act
|
|
|
+ superView.Add (subView);
|
|
|
+
|
|
|
+ // Assert - SuperView should not be set because the change was cancelled
|
|
|
+ Assert.Null (subView.SuperView);
|
|
|
+ Assert.Empty (superView.SubViews);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void SuperViewChanging_Virtual_Method_Cancellation_Prevents_Event ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ var superView = new View ();
|
|
|
+ var subView = new TestViewThatCancelsChange ();
|
|
|
+
|
|
|
+ var eventRaised = false;
|
|
|
+ subView.SuperViewChanging += (s, e) =>
|
|
|
+ {
|
|
|
+ eventRaised = true;
|
|
|
+ };
|
|
|
+
|
|
|
+ // Act
|
|
|
+ superView.Add (subView);
|
|
|
+
|
|
|
+ // Assert - Event should not be raised because virtual method cancelled first
|
|
|
+ Assert.False (eventRaised);
|
|
|
+ Assert.Null (subView.SuperView);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void SuperViewChanging_Cancellation_On_Remove ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ var superView = new View ();
|
|
|
+ var subView = new View ();
|
|
|
+
|
|
|
+ superView.Add (subView);
|
|
|
+ Assert.Equal (superView, subView.SuperView);
|
|
|
+
|
|
|
+ subView.SuperViewChanging += (s, e) =>
|
|
|
+ {
|
|
|
+ // Cancel removal if trying to set to null
|
|
|
+ if (e.NewValue is null)
|
|
|
+ {
|
|
|
+ e.Handled = true;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // Act
|
|
|
+ superView.Remove (subView);
|
|
|
+
|
|
|
+ // Assert - SuperView should still be set because removal was cancelled
|
|
|
+ Assert.Equal (superView, subView.SuperView);
|
|
|
+ Assert.Single (superView.SubViews);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void SuperViewChanging_Cancellation_When_Changing_Between_SuperViews ()
|
|
|
+ {
|
|
|
+ // Arrange
|
|
|
+ var superView1 = new View ();
|
|
|
+ var superView2 = new View ();
|
|
|
+ var subView = new View ();
|
|
|
+
|
|
|
+ superView1.Add (subView);
|
|
|
+
|
|
|
+ subView.SuperViewChanging += (s, e) =>
|
|
|
+ {
|
|
|
+ // Cancel if trying to move to superView2
|
|
|
+ if (e.NewValue == superView2)
|
|
|
+ {
|
|
|
+ e.Handled = true;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // Act
|
|
|
+ superView2.Add (subView);
|
|
|
+
|
|
|
+ // Assert - Should still be in superView1 because change was cancelled
|
|
|
+ Assert.Equal (superView1, subView.SuperView);
|
|
|
+ Assert.Single (superView1.SubViews);
|
|
|
+ Assert.Empty (superView2.SubViews);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Helper class for testing cancellation
|
|
|
+ private class TestViewThatCancelsChange : View
|
|
|
+ {
|
|
|
+ protected override bool OnSuperViewChanging (ValueChangingEventArgs<View?> args)
|
|
|
+ {
|
|
|
+ return true; // Always cancel the change
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|