mirror of https://github.com/AMT-Cheif/Stylet.git
Push coverage up to 99.7%
This commit is contained in:
parent
256198d3c0
commit
fc4a7fb61c
2
Rakefile
2
Rakefile
|
@ -47,7 +47,7 @@ task :test => [:nunit_test_runner] do |t|
|
|||
end
|
||||
|
||||
desc "Launch the NUnit gui pointing at the correct DLL for CONFIG (or Debug)"
|
||||
task :nunit do |t|
|
||||
task :nunit => [:test_environment] do |t|
|
||||
sh NUNIT_EXE, UNIT_TESTS_DLL
|
||||
end
|
||||
|
||||
|
|
|
@ -30,13 +30,20 @@ namespace Stylet
|
|||
|
||||
this.Application = Application.Current;
|
||||
|
||||
// Call this before calling our Start method
|
||||
this.Application.Startup += this.OnStartup;
|
||||
this.Application.Startup += (o, e) => this.Start();
|
||||
// Allows for unit testing
|
||||
if (this.Application != null)
|
||||
{
|
||||
// Call this before calling our Start method
|
||||
this.Application.Startup += (o, e) =>
|
||||
{
|
||||
this.OnStartup(o, e);
|
||||
this.Start();
|
||||
};
|
||||
|
||||
// Make life nice for the app - they can handle these by overriding Bootstrapper methods, rather than adding event handlers
|
||||
this.Application.Exit += OnExit;
|
||||
this.Application.DispatcherUnhandledException += OnUnhandledExecption;
|
||||
// Make life nice for the app - they can handle these by overriding Bootstrapper methods, rather than adding event handlers
|
||||
this.Application.Exit += OnExit;
|
||||
this.Application.DispatcherUnhandledException += OnUnhandledExecption;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -61,8 +68,11 @@ namespace Stylet
|
|||
|
||||
protected virtual void ConfigureResources()
|
||||
{
|
||||
if (this.Application == null)
|
||||
return;
|
||||
|
||||
var rc = new ResourceDictionary() { Source = new Uri("pack://application:,,,/Stylet;component/Xaml/StyletResourceDictionary.xaml", UriKind.Absolute) };
|
||||
Application.Resources.MergedDictionaries.Add(rc);
|
||||
this.Application.Resources.MergedDictionaries.Add(rc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -95,9 +105,9 @@ namespace Stylet
|
|||
/// Initial contents of AssemblySource.Assemblies, defaults to the entry assembly
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected IEnumerable<Assembly> SelectAssemblies()
|
||||
protected virtual IEnumerable<Assembly> SelectAssemblies()
|
||||
{
|
||||
return new[] { Assembly.GetEntryAssembly() };
|
||||
return new[] { this.GetType().Assembly };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -110,7 +120,7 @@ namespace Stylet
|
|||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
protected virtual void OnExit(object sender, EventArgs e) { }
|
||||
protected virtual void OnExit(object sender, ExitEventArgs e) { }
|
||||
|
||||
/// <summary>
|
||||
/// Hook called on an unhandled exception
|
||||
|
|
|
@ -43,7 +43,9 @@ namespace StyletIoC
|
|||
|
||||
var memberAccess = Expression.MakeMemberAccess(objExpression, member);
|
||||
var memberValue = this.container.GetExpression(new TypeKey(memberType, attribute.Key), true);
|
||||
return Expression.Assign(memberAccess, memberValue);
|
||||
var assign = Expression.Assign(memberAccess, memberValue);
|
||||
// Only actually do the assignment if the field/property is currently null
|
||||
return Expression.IfThen(Expression.Equal(memberAccess, Expression.Constant(null, memberType)), assign);
|
||||
}
|
||||
|
||||
public Action<object> GetImplementor()
|
||||
|
|
|
@ -255,7 +255,7 @@ namespace StyletIoC
|
|||
|
||||
public override void Build(StyletIoCContainer container)
|
||||
{
|
||||
var candidates = from type in assemblies.SelectMany(x => x.GetTypes())
|
||||
var candidates = from type in assemblies.Distinct().SelectMany(x => x.GetTypes())
|
||||
let baseType = type.GetBaseTypesAndInterfaces().FirstOrDefault(x => x == this.serviceType || x.IsGenericType && x.GetGenericTypeDefinition() == this.serviceType)
|
||||
where baseType != null
|
||||
select new { Type = type, Base = baseType.ContainsGenericParameters ? baseType.GetGenericTypeDefinition() : baseType };
|
||||
|
@ -377,18 +377,13 @@ namespace StyletIoC
|
|||
assemblies = new[] { Assembly.GetCallingAssembly() };
|
||||
|
||||
// We self-bind concrete classes only
|
||||
var classes = assemblies.SelectMany(x => x.GetTypes()).Where(c => c.IsClass && !c.IsAbstract);
|
||||
var classes = assemblies.Distinct().SelectMany(x => x.GetTypes()).Where(c => c.IsClass && !c.IsAbstract);
|
||||
foreach (var cls in classes)
|
||||
{
|
||||
// Don't care if binding fails - we're likely to hit a few of these
|
||||
try
|
||||
{
|
||||
this.BindWeak(cls).To(cls);
|
||||
}
|
||||
catch (StyletIoCRegistrationException e)
|
||||
{
|
||||
Debug.WriteLine(String.Format("Unable to auto-bind type {0}: {1}", cls.Description(), e.Message), "StyletIoC");
|
||||
}
|
||||
// It's not actually possible for this to fail with a StyletIoCRegistrationException (at least currently)
|
||||
// It's a self-binding, and those are always safe (at this stage - it could fall over when the containing's actually build)
|
||||
|
||||
this.BindWeak(cls).To(cls);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +407,7 @@ namespace StyletIoC
|
|||
{
|
||||
var container = new StyletIoCContainer();
|
||||
container.AddRegistration(new TypeKey(typeof(IContainer), null), new SingletonRegistration(new FactoryCreator<StyletIoCContainer>(c => container, container)));
|
||||
container.AddRegistration(new TypeKey(typeof(StyletIoCContainer), null), new SingletonRegistration(new FactoryCreator<StyletIoCContainer>(c => container, container)));
|
||||
//container.AddRegistration(new TypeKey(typeof(StyletIoCContainer), null), new SingletonRegistration(new FactoryCreator<StyletIoCContainer>(c => container, container)));
|
||||
|
||||
// For each TypeKey, we remove any weak bindings if there are any strong bindings
|
||||
var groups = this.bindings.GroupBy(x => new { Key = x.Key, Type = x.ServiceType });
|
||||
|
|
|
@ -174,8 +174,9 @@ namespace StyletIoC
|
|||
throw new ArgumentNullException("type");
|
||||
var typeKey = new TypeKey(type, key);
|
||||
IRegistration registration;
|
||||
if (!this.TryRetrieveGetAllRegistrationFromElementType(typeKey, null, out registration))
|
||||
throw new StyletIoCRegistrationException(String.Format("Could not find registration for type {0} and key '{1}'", typeKey.Type.Description(), typeKey.Key));
|
||||
// This can currently never fail, since we pass in null
|
||||
var result = this.TryRetrieveGetAllRegistrationFromElementType(typeKey, null, out registration);
|
||||
Debug.Assert(result);
|
||||
var generator = registration.GetGenerator();
|
||||
return (IEnumerable<object>)generator();
|
||||
}
|
||||
|
@ -345,8 +346,8 @@ namespace StyletIoC
|
|||
newType = unboundGeneric.Type.MakeGenericType(unboundGeneric.Type.GetTypeInfo().GenericTypeParameters.Select(x => mapping.Single(t => t.Name.Name == x.Name).Type).ToArray());
|
||||
}
|
||||
|
||||
if (!type.IsAssignableFrom(newType))
|
||||
continue;
|
||||
// The binder should have made sure of this
|
||||
Debug.Assert(type.IsAssignableFrom(newType));
|
||||
|
||||
// Right! We've made a new generic type we can use
|
||||
var registration = unboundGeneric.CreateRegistrationForType(newType);
|
||||
|
@ -571,14 +572,9 @@ namespace StyletIoC
|
|||
|
||||
public static IEnumerable<Type> GetBaseTypes(this Type type)
|
||||
{
|
||||
if (type == typeof(object))
|
||||
yield break;
|
||||
var baseType = type.BaseType ?? typeof(object);
|
||||
|
||||
while (baseType != null)
|
||||
for (var baseType = type.BaseType; baseType != null; baseType = baseType.BaseType)
|
||||
{
|
||||
yield return baseType;
|
||||
baseType = baseType.BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -635,7 +631,6 @@ namespace StyletIoC
|
|||
public class StyletIoCFindConstructorException : StyletIoCException
|
||||
{
|
||||
public StyletIoCFindConstructorException(string message) : base(message) { }
|
||||
public StyletIoCFindConstructorException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
|
||||
public class StyletIoCCreateFactoryException : StyletIoCException
|
||||
|
|
|
@ -18,6 +18,13 @@ namespace Stylet
|
|||
|
||||
public class WindowManager : IWindowManager
|
||||
{
|
||||
private IViewManager viewManager;
|
||||
|
||||
public WindowManager(IViewManager viewManager)
|
||||
{
|
||||
this.viewManager = viewManager;
|
||||
}
|
||||
|
||||
public void ShowWindow(object viewModel)
|
||||
{
|
||||
this.CreateWindow(viewModel, false).Show();
|
||||
|
@ -28,16 +35,14 @@ namespace Stylet
|
|||
return this.CreateWindow(viewModel, true).ShowDialog();
|
||||
}
|
||||
|
||||
private Window CreateWindow(object viewModel, bool isDialog)
|
||||
protected virtual Window CreateWindow(object viewModel, bool isDialog)
|
||||
{
|
||||
var viewManager = IoC.Get<IViewManager>();
|
||||
|
||||
var view = viewManager.CreateViewForModel(viewModel);
|
||||
var view = this.viewManager.CreateViewForModel(viewModel);
|
||||
var window = view as Window;
|
||||
if (window == null)
|
||||
throw new Exception(String.Format("Tried to show {0} as a window, but it isn't a Window", view == null ? "(null)" : view.GetType().Name));
|
||||
|
||||
viewManager.BindViewToModel(window, viewModel);
|
||||
this.viewManager.BindViewToModel(window, viewModel);
|
||||
|
||||
var haveDisplayName = viewModel as IHaveDisplayName;
|
||||
if (haveDisplayName != null)
|
||||
|
@ -139,9 +144,8 @@ namespace Stylet
|
|||
if (await task)
|
||||
{
|
||||
this.window.Closing -= this.WindowClosing;
|
||||
this.window.StateChanged -= this.WindowStateChanged;
|
||||
ScreenExtensions.TryClose(this.viewModel);
|
||||
this.window.Close();
|
||||
// The Closed event handler handles unregistering the events, and closing the ViewModel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
<Window x:Class="StyletIntegrationTests.Actions.ActionsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
Title="ActionsView" Height="300" Width="300">
|
||||
<DockPanel LastChildFill="False">
|
||||
<GroupBox DockPanel.Dock="Top" Header="CommandAction" Padding="10">
|
||||
<StackPanel>
|
||||
<TextBlock TextWrapping="WrapWithOverflow">Verify that the checkbox enables/disables the button, and that clicking the button shows a message box, containing the parameter in the textbox.</TextBlock>
|
||||
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Left" Command="{s:Action CommandButton}" CommandParameter="{Binding ElementName=Parameter, Path=Text}">Button</Button>
|
||||
<CheckBox DockPanel.Dock="Left" IsChecked="{Binding CheckboxIsChecked}" Margin="10,0,0,0">Enabled</CheckBox>
|
||||
<TextBox DockPanel.Dock="Left" x:Name="Parameter" Margin="10,0,0,0">Parameter</TextBox>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox DockPanel.Dock="Top" Header="EventAction">
|
||||
<StackPanel>
|
||||
<TextBlock TextWrapping="Wrap">Verify that both buttons show message boxes.</TextBlock>
|
||||
|
||||
<DockPanel LastChildFill="False">
|
||||
<Button DockPanel.Dock="Left" Click="{s:Action EventButtonNoArgs}">Button 1</Button>
|
||||
<Button DockPanel.Dock="Left" Click="{s:Action EventButtonWithArgs}">Button 2</Button>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
</Window>
|
|
@ -1,50 +0,0 @@
|
|||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace StyletIntegrationTests.Actions
|
||||
{
|
||||
public class ActionsViewModel : Screen
|
||||
{
|
||||
private bool _checkboxIsChecked;
|
||||
public bool CheckboxIsChecked
|
||||
{
|
||||
get { return this._checkboxIsChecked; }
|
||||
set
|
||||
{
|
||||
this.SetAndNotify(ref this._checkboxIsChecked, value);
|
||||
this.NotifyOfPropertyChange(() => this.CanCommandButton);
|
||||
}
|
||||
}
|
||||
|
||||
public ActionsViewModel()
|
||||
{
|
||||
this.DisplayName = "Actions";
|
||||
}
|
||||
|
||||
public bool CanCommandButton
|
||||
{
|
||||
get { return this.CheckboxIsChecked; }
|
||||
}
|
||||
public void CommandButton(string parameter)
|
||||
{
|
||||
MessageBox.Show(String.Format("Parameter is '{0}'", parameter));
|
||||
}
|
||||
|
||||
public void EventButtonNoArgs()
|
||||
{
|
||||
MessageBox.Show("Success!");
|
||||
}
|
||||
|
||||
public void EventButtonWithArgs(RoutedEventArgs e)
|
||||
{
|
||||
string buttonText = (string)(((Button)e.Source).Content);
|
||||
MessageBox.Show(buttonText == "Button 2" ? "Success!" : "Fail: Sender was not sent successfully");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using Stylet;
|
||||
using StyletIntegrationTests.BootstrapperIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -12,12 +11,6 @@ namespace StyletIntegrationTests
|
|||
{
|
||||
public class Bootstrapper : Bootstrapper<ShellViewModel>
|
||||
{
|
||||
protected override void ConfigureIoC(StyletIoC.IStyletIoCBuilder builder)
|
||||
{
|
||||
base.ConfigureIoC(builder); // Calling this just to trigger some code coverage
|
||||
builder.Bind<BootstrapperIoCI1>().ToAllImplementations();
|
||||
}
|
||||
|
||||
protected override void OnUnhandledExecption(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
base.OnUnhandledExecption(sender, e); // Calling this just to trigger some code coverage
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
<Window x:Class="StyletIntegrationTests.BootstrapperIoC.WindowView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
Title="DialogView" Width="300" SizeToContent="Height">
|
||||
<DockPanel Margin="20" LastChildFill="False">
|
||||
<TextBlock DockPanel.Dock="Top" TextWrapping="WrapWithOverflow">Make sure that pressing the following buttons has no visible effect (no dialogs, crashes, etc).</TextBlock>
|
||||
<Button DockPanel.Dock="Top" Command="{s:Action GetSingle}" Margin="0,10,0,0">GetSingle</Button>
|
||||
<Button DockPanel.Dock="Top" Command="{s:Action GetAll}" Margin="0,10,0,0">GetAll</Button>
|
||||
<Button DockPanel.Dock="Top" Command="{s:Action BuildUp}" Margin="0,10,0,0">BuildUp</Button>
|
||||
</DockPanel>
|
||||
</Window>
|
|
@ -1,27 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace StyletIntegrationTests.BootstrapperIoC
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for WindowView.xaml
|
||||
/// </summary>
|
||||
public partial class WindowView : Window
|
||||
{
|
||||
public WindowView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIntegrationTests.BootstrapperIoC
|
||||
{
|
||||
interface BootstrapperIoCI1 { }
|
||||
class BootstrapperIoCC1 : BootstrapperIoCI1 { }
|
||||
class BootstrapperIoCC2 : BootstrapperIoCI1 { }
|
||||
class BootstrapperIoCC3
|
||||
{
|
||||
[Inject]
|
||||
public BootstrapperIoCC1 C1 { get; set; }
|
||||
}
|
||||
|
||||
public class WindowViewModel : Screen
|
||||
{
|
||||
public void GetSingle()
|
||||
{
|
||||
var result = IoC.Get<BootstrapperIoCC1>();
|
||||
if (result == null)
|
||||
throw new Exception("IoC.Get failed");
|
||||
}
|
||||
|
||||
public void GetAll()
|
||||
{
|
||||
var result = IoC.GetAll<BootstrapperIoCI1>().ToList();
|
||||
if (result.Count != 2 || !(result[0] is BootstrapperIoCC1) || !(result[1] is BootstrapperIoCC2))
|
||||
throw new Exception("IoC.GetAll failed");
|
||||
}
|
||||
|
||||
public void BuildUp()
|
||||
{
|
||||
var c3 = new BootstrapperIoCC3();
|
||||
IoC.BuildUp(c3);
|
||||
if (c3.C1 == null)
|
||||
throw new Exception("IoC.BuildUp failed");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<Window x:Class="StyletIntegrationTests.OnUnhandledException.WindowView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
Title="WindowView" Width="300" SizeToContent="Height">
|
||||
<DockPanel Margin="20" LastChildFill="False">
|
||||
<TextBlock DockPanel.Dock="Top" TextWrapping="WrapWithOverflow">Verify that pressing the button below shows a dialog, containing the message 'Unhandled Exception: Hello'.</TextBlock>
|
||||
<Button DockPanel.Dock="Top" Command="{s:Action ThrowException}">Throw Exception</Button>
|
||||
</DockPanel>
|
||||
</Window>
|
|
@ -1,27 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace StyletIntegrationTests.OnUnhandledException
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for WindowView.xaml
|
||||
/// </summary>
|
||||
public partial class WindowView : Window
|
||||
{
|
||||
public WindowView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIntegrationTests.OnUnhandledException
|
||||
{
|
||||
public class WindowViewModel : Screen
|
||||
{
|
||||
public void ThrowException()
|
||||
{
|
||||
throw new Exception("Hello");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,28 +12,22 @@
|
|||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox DockPanel.Dock="Top" Header="Window DisplayName Bound" Padding="10">
|
||||
<Button Command="{s:Action ShowWindowsDisplayNameBound}">Show Window</Button>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox DockPanel.Dock="Top" Header="Window Guard Close" Padding="10">
|
||||
<Button Command="{s:Action ShowWindowGuardClose}">Show Window</Button>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox DockPanel.Dock="Top" Header="Window Lifecycle" Padding="10">
|
||||
<Button Command="{s:Action ShowWindowLifecycle}">Show Window</Button>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox DockPanel.Dock="Top" Header="Bootstrapper IoC" Padding="10">
|
||||
<Button Command="{s:Action ShowBootstrapperIoC}">Show Window</Button>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox DockPanel.Dock="Top" Header="OnUnhandledException" Padding="10">
|
||||
<Button Command="{s:Action ShowOnUnhandledException}">Show Window</Button>
|
||||
<DockPanel>
|
||||
<TextBlock DockPanel.Dock="Top" TextWrapping="WrapWithOverflow">Verify that pressing the button below shows a dialog, containing the message 'Unhandled Exception: Hello'.</TextBlock>
|
||||
<Button DockPanel.Dock="Top" Command="{s:Action ThrowException}">Throw Exception</Button>
|
||||
</DockPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox DockPanel.Dock="Top" Header="Actions" Padding="10">
|
||||
<Button Command="{s:Action ShowActions}">Show Window</Button>
|
||||
<GroupBox DockPanel.Dock="Top" Header="Dispatcher" Padding="10">
|
||||
<DockPanel>
|
||||
<TextBlock DockPanel.Dock="Top" TextWrapping="WrapWithOverflow">Verify that pressing the button shows a MessageBox saying 'Success'.</TextBlock>
|
||||
<Button DockPanel.Dock="Top" Command="{s:Action TestDispatcher}">Test Dispatcher</Button>
|
||||
</DockPanel>
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace StyletIntegrationTests
|
||||
{
|
||||
|
@ -32,40 +33,36 @@ namespace StyletIntegrationTests
|
|||
this.ShowDialogAndDialogResultDialogResult = this.windowManager.ShowDialog(dialog);
|
||||
}
|
||||
|
||||
public void ShowWindowsDisplayNameBound()
|
||||
{
|
||||
var window = new WindowDisplayNameBound.WindowViewModel();
|
||||
this.windowManager.ShowWindow(window);
|
||||
}
|
||||
|
||||
public void ShowWindowGuardClose()
|
||||
{
|
||||
var window = new WindowGuardClose.WindowViewModel();
|
||||
this.windowManager.ShowWindow(window);
|
||||
}
|
||||
|
||||
public void ShowWindowLifecycle()
|
||||
{
|
||||
var window = new WindowLifecycle.WindowViewModel();
|
||||
this.windowManager.ShowWindow(window);
|
||||
}
|
||||
|
||||
public void ShowBootstrapperIoC()
|
||||
public void ThrowException()
|
||||
{
|
||||
var window = new BootstrapperIoC.WindowViewModel();
|
||||
this.windowManager.ShowWindow(window);
|
||||
throw new Exception("Hello");
|
||||
}
|
||||
|
||||
public void ShowOnUnhandledException()
|
||||
public async void TestDispatcher()
|
||||
{
|
||||
var window = new OnUnhandledException.WindowViewModel();
|
||||
this.windowManager.ShowWindow(window);
|
||||
}
|
||||
var dispatcher = Execute.Dispatcher;
|
||||
var log = new List<string>();
|
||||
|
||||
public void ShowActions()
|
||||
{
|
||||
var window = new Actions.ActionsViewModel();
|
||||
this.windowManager.ShowDialog(window);
|
||||
await Task.Run(() => dispatcher.Send(() => { lock(log) { log.Add("One"); }; }));
|
||||
lock (log) { log.Add("Two"); };
|
||||
|
||||
await Task.Run(() => dispatcher.Post(() => { lock (log) { log.Add("Three"); }; }));
|
||||
lock (log) { log.Add("Four"); };
|
||||
|
||||
// OK, so at this point there's a queued message saying to add Three to the log
|
||||
// Give the main thread time to process that message
|
||||
await Task.Delay(100);
|
||||
|
||||
if (log.SequenceEqual(new[] { "One", "Two", "Four", "Three" }))
|
||||
MessageBox.Show("Success");
|
||||
else
|
||||
MessageBox.Show("Failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,16 +55,7 @@
|
|||
</ApplicationDefinition>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Actions\ActionsViewModel.cs" />
|
||||
<Compile Include="Bootstrapper.cs" />
|
||||
<Compile Include="BootstrapperIoC\WindowView.xaml.cs">
|
||||
<DependentUpon>WindowView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="BootstrapperIoC\WindowViewModel.cs" />
|
||||
<Compile Include="OnUnhandledException\WindowView.xaml.cs">
|
||||
<DependentUpon>WindowView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="OnUnhandledException\WindowViewModel.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
@ -80,8 +71,6 @@
|
|||
</Compile>
|
||||
<Compile Include="ShellViewModel.cs" />
|
||||
<Compile Include="ShowDialogAndDialogResult\DialogViewModel.cs" />
|
||||
<Compile Include="WindowDisplayNameBound\WindowViewModel.cs" />
|
||||
<Compile Include="WindowGuardClose\WindowViewModel.cs" />
|
||||
<Compile Include="WindowLifecycle\WindowViewModel.cs" />
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
|
@ -103,18 +92,6 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="Actions\ActionsView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="BootstrapperIoC\WindowView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="OnUnhandledException\WindowView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="ShellView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
@ -123,14 +100,6 @@
|
|||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WindowDisplayNameBound\WindowView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WindowGuardClose\WindowView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WindowLifecycle\WindowView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<Window x:Class="StyletIntegrationTests.WindowDisplayNameBound.WindowView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
Title="WindowView" Height="300" Width="300">
|
||||
<DockPanel Margin="10" LastChildFill="False">
|
||||
<TextBlock DockPanel.Dock="Top" TextWrapping="WrapWithOverflow">Press the button, and verify that the count in the window title increases. When you are done, close the window.</TextBlock>
|
||||
<Button DockPanel.Dock="Top" Command="{s:Action AddCount}">Press Me</Button>
|
||||
</DockPanel>
|
||||
</Window>
|
|
@ -1,25 +0,0 @@
|
|||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIntegrationTests.WindowDisplayNameBound
|
||||
{
|
||||
public class WindowViewModel : Screen
|
||||
{
|
||||
private int count = 0;
|
||||
|
||||
public WindowViewModel()
|
||||
{
|
||||
this.DisplayName = String.Format("Count: {0}", this.count);
|
||||
}
|
||||
|
||||
public void AddCount()
|
||||
{
|
||||
this.count++;
|
||||
this.DisplayName = String.Format("Count: {0}", this.count);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<Window x:Class="StyletIntegrationTests.WindowGuardClose.WindowView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
Title="WindowView" Height="300" Width="300">
|
||||
<DockPanel Margin="10">
|
||||
<TextBlock DockPanel.Dock="Top" TextWrapping="WrapWithOverflow">Leave the checkbox unchecked, then close the window using the red X at the top. It should not close.</TextBlock>
|
||||
<TextBlock DockPanel.Dock="Top" TextWrapping="WrapWithOverflow">Check the checkbox, then close the window again. It should close after 3 seconds.</TextBlock>
|
||||
<CheckBox DockPanel.Dock="Top" IsChecked="{Binding AllowClose}" Margin="0,10,0,0">Allow Close</CheckBox>
|
||||
</DockPanel>
|
||||
</Window>
|
|
@ -1,24 +0,0 @@
|
|||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIntegrationTests.WindowGuardClose
|
||||
{
|
||||
public class WindowViewModel : Screen
|
||||
{
|
||||
public bool AllowClose { get; set; }
|
||||
|
||||
public WindowViewModel()
|
||||
{
|
||||
this.DisplayName = "Window Guard Close";
|
||||
}
|
||||
|
||||
public override Task<bool> CanCloseAsync()
|
||||
{
|
||||
return this.AllowClose ? Task.Delay(2000).ContinueWith(t => true) : Task.FromResult(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ namespace StyletUnitTests
|
|||
public void SetUpFixture()
|
||||
{
|
||||
Execute.TestExecuteSynchronously = true;
|
||||
AssemblySource.Assemblies.Clear();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace StyletUnitTests
|
||||
{
|
||||
[TestFixture, RequiresSTA]
|
||||
public class BootstrapperBaseTests
|
||||
{
|
||||
private class RootViewModel { }
|
||||
|
||||
private class MyBootstrapperBase<T> : BootstrapperBase<T> where T : class
|
||||
{
|
||||
private IViewManager viewManager;
|
||||
private IWindowManager windowManager;
|
||||
|
||||
public MyBootstrapperBase(IViewManager viewManager, IWindowManager windowManager)
|
||||
{
|
||||
this.viewManager = viewManager;
|
||||
this.windowManager = windowManager;
|
||||
}
|
||||
|
||||
public bool GetInstanceCalled;
|
||||
protected override object GetInstance(Type service, string key = null)
|
||||
{
|
||||
this.GetInstanceCalled = true;
|
||||
if (service == typeof(IViewManager))
|
||||
return this.viewManager;
|
||||
if (service == typeof(IWindowManager))
|
||||
return this.windowManager;
|
||||
if (service == typeof(RootViewModel))
|
||||
return new RootViewModel();
|
||||
return new object();
|
||||
}
|
||||
|
||||
public bool GetAllInstancesCalled;
|
||||
protected override IEnumerable<object> GetAllInstances(Type service)
|
||||
{
|
||||
this.GetAllInstancesCalled = true;
|
||||
return Enumerable.Empty<object>();
|
||||
}
|
||||
|
||||
public bool BuildUpCalled;
|
||||
protected override void BuildUp(object instance)
|
||||
{
|
||||
this.BuildUpCalled = true;
|
||||
}
|
||||
|
||||
public bool OnExitCalled;
|
||||
protected override void OnExit(object sender, ExitEventArgs e)
|
||||
{
|
||||
this.OnExitCalled = true;
|
||||
}
|
||||
|
||||
public bool ConfigureResourcesCalled;
|
||||
protected override void ConfigureResources()
|
||||
{
|
||||
this.ConfigureResourcesCalled = true;
|
||||
base.ConfigureResources();
|
||||
}
|
||||
|
||||
public bool ConfigureCalled;
|
||||
protected override void Configure()
|
||||
{
|
||||
this.ConfigureCalled = true;
|
||||
base.Configure();
|
||||
}
|
||||
|
||||
public new void Start()
|
||||
{
|
||||
base.Start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private MyBootstrapperBase<RootViewModel> bootstrapper;
|
||||
private Mock<IViewManager> viewManager;
|
||||
private Mock<IWindowManager> windowManager;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void FixtureSetUp()
|
||||
{
|
||||
Execute.TestExecuteSynchronously = true;
|
||||
AssemblySource.Assemblies.Clear();
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
this.viewManager = new Mock<IViewManager>();
|
||||
this.windowManager = new Mock<IWindowManager>();
|
||||
this.bootstrapper = new MyBootstrapperBase<RootViewModel>(this.viewManager.Object, this.windowManager.Object);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetsUpOnExitHandler()
|
||||
{
|
||||
var ctor = typeof(ExitEventArgs).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];
|
||||
var ea = (ExitEventArgs)ctor.Invoke(new object[] { 3 });
|
||||
//this.application.OnExit(ea);
|
||||
//Assert.True(this.bootstrapper.OnExitCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssignsIoCGetInstanceToGetInstance()
|
||||
{
|
||||
IoC.GetInstance(typeof(string), null);
|
||||
Assert.True(this.bootstrapper.GetInstanceCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssignsIoCGetAllInstancesToGetAllInstances()
|
||||
{
|
||||
IoC.GetAllInstances(typeof(string));
|
||||
Assert.True(this.bootstrapper.GetAllInstancesCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssignsIoCBuildUpToBuildUp()
|
||||
{
|
||||
IoC.BuildUp(new object());
|
||||
Assert.True(this.bootstrapper.BuildUpCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StartAssignsExecuteDispatcher()
|
||||
{
|
||||
Execute.Dispatcher = null;
|
||||
this.bootstrapper.Start();
|
||||
Assert.NotNull(Execute.Dispatcher); // Can't test any further, unfortunately
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StartSetsUpAssemblySource()
|
||||
{
|
||||
AssemblySource.Assemblies.Add(null);
|
||||
this.bootstrapper.Start();
|
||||
Assert.That(AssemblySource.Assemblies, Is.EquivalentTo(new[] { this.bootstrapper.GetType().Assembly }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StartCallsConfigureResources()
|
||||
{
|
||||
this.bootstrapper.Start();
|
||||
Assert.True(this.bootstrapper.ConfigureResourcesCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StartCallsConfigure()
|
||||
{
|
||||
this.bootstrapper.Start();
|
||||
Assert.True(this.bootstrapper.ConfigureCalled);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletUnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class BootstrapperTests
|
||||
{
|
||||
private interface I1 { }
|
||||
private class C1 : I1 { }
|
||||
|
||||
private class RootViewModel { }
|
||||
|
||||
private class MyBootstrapper<T> : Bootstrapper<T> where T : class
|
||||
{
|
||||
public IContainer Container
|
||||
{
|
||||
get { return base.container; }
|
||||
set { base.container = value; }
|
||||
}
|
||||
|
||||
public new void Configure()
|
||||
{
|
||||
base.Configure();
|
||||
}
|
||||
|
||||
public bool ConfigureIoCCalled;
|
||||
protected override void ConfigureIoC(IStyletIoCBuilder builder)
|
||||
{
|
||||
this.ConfigureIoCCalled = true;
|
||||
builder.Bind<I1>().To<C1>();
|
||||
base.ConfigureIoC(builder);
|
||||
}
|
||||
|
||||
public new object GetInstance(Type service, string key)
|
||||
{
|
||||
return base.GetInstance(service, key);
|
||||
}
|
||||
|
||||
public new IEnumerable<object> GetAllInstances(Type service)
|
||||
{
|
||||
return base.GetAllInstances(service);
|
||||
}
|
||||
|
||||
public new void BuildUp(object instance)
|
||||
{
|
||||
base.BuildUp(instance);
|
||||
}
|
||||
}
|
||||
|
||||
private MyBootstrapper<RootViewModel> bootstrapper;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void FixtureSetUp()
|
||||
{
|
||||
Execute.TestExecuteSynchronously = true;
|
||||
AssemblySource.Assemblies.Clear();
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
this.bootstrapper = new MyBootstrapper<RootViewModel>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConfigureBindsRequiredTypes()
|
||||
{
|
||||
AssemblySource.Assemblies.Add(this.GetType().Assembly);
|
||||
this.bootstrapper.Configure();
|
||||
var ioc = this.bootstrapper.Container;
|
||||
|
||||
Assert.IsInstanceOf<WindowManager>(ioc.Get<IWindowManager>());
|
||||
Assert.IsInstanceOf<IEventAggregator>(ioc.Get<IEventAggregator>());
|
||||
Assert.IsInstanceOf<ViewManager>(ioc.Get<IViewManager>());
|
||||
|
||||
// Test autobinding
|
||||
Assert.DoesNotThrow(() => ioc.Get<RootViewModel>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConfigureCallsConfigureIoCWithCorrectBuilder()
|
||||
{
|
||||
AssemblySource.Assemblies.Add(this.GetType().Assembly);
|
||||
this.bootstrapper.Configure();
|
||||
var ioc = this.bootstrapper.Container;
|
||||
|
||||
Assert.True(this.bootstrapper.ConfigureIoCCalled);
|
||||
Assert.IsInstanceOf<C1>(ioc.Get<I1>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetInstanceMappedToContainer()
|
||||
{
|
||||
var container = new Mock<IContainer>();
|
||||
this.bootstrapper.Container = container.Object;
|
||||
|
||||
container.Setup(x => x.Get(typeof(string), "test")).Returns("hello").Verifiable();
|
||||
var result = this.bootstrapper.GetInstance(typeof(string), "test");
|
||||
Assert.AreEqual("hello", result);
|
||||
container.Verify();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetAllInstancesMappedToContainer()
|
||||
{
|
||||
var container = new Mock<IContainer>();
|
||||
this.bootstrapper.Container = container.Object;
|
||||
|
||||
container.Setup(x => x.GetAll(typeof(int), null)).Returns(new object[] { 1, 2, 3 }).Verifiable();
|
||||
var result = this.bootstrapper.GetAllInstances(typeof(int));
|
||||
Assert.That(result, Is.EquivalentTo(new[] { 1, 2, 3 }));
|
||||
container.Verify();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildUpMappedToContainer()
|
||||
{
|
||||
var container = new Mock<IContainer>();
|
||||
this.bootstrapper.Container = container.Object;
|
||||
|
||||
var instance = new object();
|
||||
container.Setup(x => x.BuildUp(instance)).Verifiable();
|
||||
this.bootstrapper.BuildUp(instance);
|
||||
container.Verify();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,108 +9,108 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace StyletUnitTests
|
||||
{
|
||||
interface I1 { }
|
||||
|
||||
class C1 : I1 { }
|
||||
class C2 : I1
|
||||
{
|
||||
public C1 C1;
|
||||
public C2(C1 c1)
|
||||
{
|
||||
this.C1 = c1;
|
||||
}
|
||||
}
|
||||
|
||||
class C3
|
||||
{
|
||||
public C1 C1;
|
||||
public C2 C2;
|
||||
public C3(C1 c1, C2 c2)
|
||||
{
|
||||
this.C1 = c1;
|
||||
this.C2 = c2;
|
||||
}
|
||||
}
|
||||
|
||||
class C4
|
||||
{
|
||||
public C1 C1;
|
||||
public C4([Inject("key1")] C1 c1)
|
||||
{
|
||||
this.C1 = c1;
|
||||
}
|
||||
}
|
||||
|
||||
class C5
|
||||
{
|
||||
public bool RightConstructorCalled;
|
||||
public C5(C1 c1, C2 c2 = null, C3 c3 = null, C4 c4 = null)
|
||||
{
|
||||
}
|
||||
|
||||
public C5(C1 c1, C2 c2, C3 c3 = null)
|
||||
{
|
||||
this.RightConstructorCalled = true;
|
||||
}
|
||||
|
||||
public C5(C1 c1, C2 c2)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class C6
|
||||
{
|
||||
public bool RightConstructorCalled;
|
||||
[Inject]
|
||||
public C6(C1 c1)
|
||||
{
|
||||
this.RightConstructorCalled = true;
|
||||
}
|
||||
|
||||
public C6(C1 c1, C2 c2)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class C7
|
||||
{
|
||||
[Inject]
|
||||
public C7()
|
||||
{
|
||||
}
|
||||
|
||||
[Inject]
|
||||
public C7(C1 c1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class C8
|
||||
{
|
||||
public IEnumerable<I1> I1s;
|
||||
public C8(IEnumerable<I1> i1s)
|
||||
{
|
||||
this.I1s = i1s;
|
||||
}
|
||||
}
|
||||
|
||||
class C9
|
||||
{
|
||||
public C9(I1 i1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class C10
|
||||
{
|
||||
public C10(ObservableCollection<C10> c1s)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class StyletIoCConstructorInjectionTests
|
||||
{
|
||||
interface I1 { }
|
||||
|
||||
class C1 : I1 { }
|
||||
class C2 : I1
|
||||
{
|
||||
public C1 C1;
|
||||
public C2(C1 c1)
|
||||
{
|
||||
this.C1 = c1;
|
||||
}
|
||||
}
|
||||
|
||||
class C3
|
||||
{
|
||||
public C1 C1;
|
||||
public C2 C2;
|
||||
public C3(C1 c1, C2 c2)
|
||||
{
|
||||
this.C1 = c1;
|
||||
this.C2 = c2;
|
||||
}
|
||||
}
|
||||
|
||||
class C4
|
||||
{
|
||||
public C1 C1;
|
||||
public C4([Inject("key1")] C1 c1)
|
||||
{
|
||||
this.C1 = c1;
|
||||
}
|
||||
}
|
||||
|
||||
class C5
|
||||
{
|
||||
public bool RightConstructorCalled;
|
||||
public C5(C1 c1, C2 c2 = null, C3 c3 = null, C4 c4 = null)
|
||||
{
|
||||
}
|
||||
|
||||
public C5(C1 c1, C2 c2, C3 c3 = null)
|
||||
{
|
||||
this.RightConstructorCalled = true;
|
||||
}
|
||||
|
||||
public C5(C1 c1, C2 c2)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class C6
|
||||
{
|
||||
public bool RightConstructorCalled;
|
||||
[Inject]
|
||||
public C6(C1 c1)
|
||||
{
|
||||
this.RightConstructorCalled = true;
|
||||
}
|
||||
|
||||
public C6(C1 c1, C2 c2)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class C7
|
||||
{
|
||||
[Inject]
|
||||
public C7()
|
||||
{
|
||||
}
|
||||
|
||||
[Inject]
|
||||
public C7(C1 c1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class C8
|
||||
{
|
||||
public IEnumerable<I1> I1s;
|
||||
public C8(IEnumerable<I1> i1s)
|
||||
{
|
||||
this.I1s = i1s;
|
||||
}
|
||||
}
|
||||
|
||||
class C9
|
||||
{
|
||||
public C9(I1 i1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class C10
|
||||
{
|
||||
public C10(ObservableCollection<C10> c1s)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RecursivelyPopulatesConstructorParams()
|
||||
{
|
||||
|
|
|
@ -20,6 +20,15 @@ namespace StyletUnitTests
|
|||
class C21 : IC2 { }
|
||||
class C22 : IC2 { }
|
||||
|
||||
class C3
|
||||
{
|
||||
public List<IC2> C2s;
|
||||
public C3(IEnumerable<IC2> c2s)
|
||||
{
|
||||
this.C2s = c2s.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that Bind() and friends worked was done in StyletIoCGetSingleTests
|
||||
|
||||
[Test]
|
||||
|
@ -172,5 +181,24 @@ namespace StyletUnitTests
|
|||
var ioc = builder.BuildContainer();
|
||||
Assert.Throws<ArgumentNullException>(() => ioc.GetTypeOrAll(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CachedGetAllExpressionWorks()
|
||||
{
|
||||
// The GetAll creator's instance expression can be cached. This ensures that that works
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<IC2>().To<C21>();
|
||||
builder.Bind<IC2>().To<C22>();
|
||||
builder.Bind<C3>().ToSelf();
|
||||
var ioc = builder.BuildContainer();
|
||||
|
||||
var c2s = ioc.GetAll<IC2>().ToList();
|
||||
var c3 = ioc.Get<C3>();
|
||||
|
||||
Assert.NotNull(c3.C2s);
|
||||
Assert.AreEqual(2, c3.C2s.Count);
|
||||
Assert.AreNotEqual(c2s[0], c3.C2s[0]);
|
||||
Assert.AreNotEqual(c2s[1], c3.C2s[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,14 @@ namespace StyletUnitTests
|
|||
interface IC1 { }
|
||||
class C1 : IC1 { }
|
||||
class C12 : IC1 { }
|
||||
class C2
|
||||
{
|
||||
public C1 C1;
|
||||
public C2(C1 c1)
|
||||
{
|
||||
this.C1 = c1;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SelfTransientBindingResolvesGeneric()
|
||||
|
@ -210,5 +218,21 @@ namespace StyletUnitTests
|
|||
var ioc = builder.BuildContainer();
|
||||
Assert.Throws<ArgumentNullException>(() => ioc.Get(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CachedFactoryInstanceExpressionWorks()
|
||||
{
|
||||
// The factory's instance expression can be cached. This ensures that that works
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C1>().ToFactory(x => new C1());
|
||||
builder.Bind<C2>().ToSelf();
|
||||
var ioc = builder.BuildContainer();
|
||||
|
||||
var c1 = ioc.Get<C1>();
|
||||
var c2 = ioc.Get<C2>();
|
||||
|
||||
Assert.NotNull(c2.C1);
|
||||
Assert.AreNotEqual(c1, c2.C1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,5 +188,19 @@ namespace StyletUnitTests
|
|||
|
||||
Assert.IsInstanceOf<C1>(subject.C1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildUpDoesNotReplaceAlreadySetProperties()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C1>().ToSelf();
|
||||
var ioc = builder.BuildContainer();
|
||||
|
||||
var s = new Subject1();
|
||||
ioc.BuildUp(s);
|
||||
var firstC1 = s.C1;
|
||||
ioc.BuildUp(s);
|
||||
Assert.AreEqual(s.C1, firstC1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace StyletUnitTests
|
|||
{
|
||||
interface I1<T> { }
|
||||
class C1<T> : I1<T> { }
|
||||
class C12<T> { }
|
||||
|
||||
interface I2<T, U> { }
|
||||
class C2<T, U> : I2<U, T> { }
|
||||
|
@ -77,5 +78,12 @@ namespace StyletUnitTests
|
|||
builder.Bind(typeof(C1<>)).ToSelf();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => builder.BuildContainer());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowsIfUnboundGenericDoesNotImplementService()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => builder.Bind(typeof(I1<>)).To(typeof(C12<>)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@
|
|||
<Compile Include="AssemblySourceTests.cs" />
|
||||
<Compile Include="BindableCollectionTests.cs" />
|
||||
<Compile Include="BoolToVisibilityConverterTests.cs" />
|
||||
<Compile Include="BootstrapperBaseTests.cs" />
|
||||
<Compile Include="BootstrapperTests.cs" />
|
||||
<Compile Include="CommandActionTests.cs" />
|
||||
<Compile Include="ConductorAllActiveTests.cs" />
|
||||
<Compile Include="ConductorNavigatingTests.cs" />
|
||||
|
|
|
@ -67,6 +67,12 @@ namespace StyletUnitTests
|
|||
|
||||
private ViewManager viewManager;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void FixtureSetUp()
|
||||
{
|
||||
AssemblySource.Assemblies.Clear();
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
|
@ -120,13 +126,13 @@ namespace StyletUnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void LocateViewforModelThrowsIfViewNotFound()
|
||||
public void LocateViewForModelThrowsIfViewNotFound()
|
||||
{
|
||||
Assert.Throws<Exception>(() => this.viewManager.LocateViewForModel(typeof(C1)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LocateViewforModelFindsViewForModel()
|
||||
public void LocateViewForModelFindsViewForModel()
|
||||
{
|
||||
Execute.TestExecuteSynchronously = true;
|
||||
AssemblySource.Assemblies.Add(Assembly.GetExecutingAssembly());
|
||||
|
|
|
@ -3,45 +3,271 @@ using NUnit.Framework;
|
|||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace StyletUnitTests
|
||||
{
|
||||
[TestFixture, RequiresSTA]
|
||||
public class WindowManagerTests
|
||||
{
|
||||
private class MyWindowManager : WindowManager
|
||||
{
|
||||
public MyWindowManager(IViewManager viewManager) : base(viewManager) { }
|
||||
|
||||
public new Window CreateWindow(object viewModel, bool isDialog)
|
||||
{
|
||||
return base.CreateWindow(viewModel, isDialog);
|
||||
}
|
||||
}
|
||||
|
||||
private class MyWindow : Window
|
||||
{
|
||||
public new void OnClosing(CancelEventArgs e)
|
||||
{
|
||||
base.OnClosing(e);
|
||||
}
|
||||
|
||||
public bool OnClosedCalled;
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
base.OnClosed(e);
|
||||
this.OnClosedCalled = true;
|
||||
}
|
||||
|
||||
public new void OnStateChanged(EventArgs e)
|
||||
{
|
||||
base.OnStateChanged(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Mock<IViewManager> viewManager;
|
||||
private WindowManager windowManager;
|
||||
private MyWindowManager windowManager;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
this.viewManager = new Mock<IViewManager>();
|
||||
this.windowManager = new WindowManager();
|
||||
this.windowManager = new MyWindowManager(this.viewManager.Object);
|
||||
|
||||
IoC.GetInstance = (service, key) => this.viewManager.Object;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShowWindowAsksViewManagerForView()
|
||||
public void CreateWindowAsksViewManagerForView()
|
||||
{
|
||||
var model = new object();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model)).Verifiable();
|
||||
// Don't care if this throws - that's OK
|
||||
try { this.windowManager.ShowWindow(model); }
|
||||
try { this.windowManager.CreateWindow(model, false); }
|
||||
catch (Exception) { }
|
||||
this.viewManager.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShowWindowThrowsIfViewIsntAWindow()
|
||||
public void CreateWindowThrowsIfViewIsntAWindow()
|
||||
{
|
||||
var model = new object();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model)).Returns(new UIElement());
|
||||
Assert.Throws<Exception>(() => this.windowManager.ShowWindow(model));
|
||||
Assert.Throws<Exception>(() => this.windowManager.CreateWindow(model, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateWindowBindsViewToModel()
|
||||
{
|
||||
var model = new object();
|
||||
var window = new Window();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model)).Returns(window);
|
||||
|
||||
this.windowManager.CreateWindow(model, false);
|
||||
|
||||
this.viewManager.Verify(x => x.BindViewToModel(window, model));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateWindowSetsUpTitleBindingIfViewModelIsIHaveDisplayName()
|
||||
{
|
||||
var model = new Screen();
|
||||
var window = new Window();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model)).Returns(window);
|
||||
|
||||
this.windowManager.CreateWindow(model, false);
|
||||
|
||||
var e = window.GetBindingExpression(Window.TitleProperty);
|
||||
Assert.AreEqual(BindingMode.TwoWay, e.ParentBinding.Mode);
|
||||
Assert.AreEqual("DisplayName", e.ParentBinding.Path.Path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateWindowActivatesViewModel()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(new Window());
|
||||
this.windowManager.CreateWindow(model.Object, false);
|
||||
model.Verify(x => x.Activate());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WindowStateChangedActivatesIfMaximized()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(window);
|
||||
this.windowManager.CreateWindow(model.Object, false);
|
||||
window.WindowState = WindowState.Maximized;
|
||||
window.OnStateChanged(EventArgs.Empty);
|
||||
model.Verify(x => x.Activate());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WindowStateChangedActivatesIfNormal()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(window);
|
||||
this.windowManager.CreateWindow(model.Object, false);
|
||||
window.WindowState = WindowState.Normal;
|
||||
window.OnStateChanged(EventArgs.Empty);
|
||||
model.Verify(x => x.Activate());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WindowStateChangedDeactivatesIfMinimized()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(window);
|
||||
this.windowManager.CreateWindow(model.Object, false);
|
||||
window.WindowState = WindowState.Minimized;
|
||||
window.OnStateChanged(EventArgs.Empty);
|
||||
model.Verify(x => x.Deactivate());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WindowClosingDoesNothingIfAlreadyCancelled()
|
||||
{
|
||||
var model = new Screen();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model)).Returns(window);
|
||||
this.windowManager.CreateWindow(model, false);
|
||||
window.OnClosing(new CancelEventArgs(true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WindowClosingCancelsIfCanCloseAsyncReturnsSynchronousFalse()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(window);
|
||||
this.windowManager.CreateWindow(model.Object, false);
|
||||
model.Setup(x => x.CanCloseAsync()).Returns(Task.FromResult(false));
|
||||
var ea = new CancelEventArgs();
|
||||
window.OnClosing(ea);
|
||||
Assert.True(ea.Cancel);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WindowClosingDoesNotCancelIfCanCloseAsyncReturnsSynchronousTrue()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(window);
|
||||
this.windowManager.CreateWindow(model.Object, false);
|
||||
model.Setup(x => x.CanCloseAsync()).Returns(Task.FromResult(true));
|
||||
var ea = new CancelEventArgs();
|
||||
window.OnClosing(ea);
|
||||
Assert.False(ea.Cancel);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WindowClosingCancelsIfCanCloseAsyncReturnsAsynchronousFalse()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(window);
|
||||
this.windowManager.CreateWindow(model.Object, false);
|
||||
model.Setup(x => x.CanCloseAsync()).Returns(Task.Delay(1).ContinueWith(t => false));
|
||||
var ea = new CancelEventArgs();
|
||||
window.OnClosing(ea);
|
||||
Assert.True(ea.Cancel);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WindowClosingCancelsIfCanCloseAsyncReturnsAsynchronousTrue()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(window);
|
||||
this.windowManager.CreateWindow(model.Object, false);
|
||||
model.Setup(x => x.CanCloseAsync()).Returns(Task.Delay(1).ContinueWith(t => true));
|
||||
var ea = new CancelEventArgs();
|
||||
window.OnClosing(ea);
|
||||
Assert.True(ea.Cancel);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WindowClosingClosesWindowIfCanCloseAsyncCompletesTrue()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(window);
|
||||
this.windowManager.CreateWindow(model.Object, false);
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
model.Setup(x => x.CanCloseAsync()).Returns(tcs.Task);
|
||||
window.OnClosing(new CancelEventArgs());
|
||||
model.Verify(x => x.Close(), Times.Never);
|
||||
tcs.SetResult(true);
|
||||
model.Verify(x => x.Close(), Times.Once);
|
||||
|
||||
Assert.True(window.OnClosedCalled);
|
||||
|
||||
// Check it didn't call WindowClosing again - just the first time
|
||||
model.Verify(x => x.CanCloseAsync(), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CloseItemDoesNothingIfItemIsWrong()
|
||||
{
|
||||
var model = new Screen();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model)).Returns(window);
|
||||
this.windowManager.CreateWindow(model, false);
|
||||
((IChildDelegate)model.Parent).CloseItem(new object());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CloseItemDoesNothingIfCanCloseReturnsFalse()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(window);
|
||||
object parent = null;
|
||||
model.SetupSet(x => x.Parent = It.IsAny<object>()).Callback((object x) => parent = x);
|
||||
this.windowManager.CreateWindow(model.Object, false);
|
||||
|
||||
model.Setup(x => x.CanCloseAsync()).Returns(Task.Delay(1).ContinueWith(t => false));
|
||||
((IChildDelegate)parent).CloseItem(model.Object);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CloseItemClosesAndWindowViewModelIfCanCloseReturnsTrue()
|
||||
{
|
||||
var model = new Mock<IScreen>();
|
||||
var window = new MyWindow();
|
||||
this.viewManager.Setup(x => x.CreateViewForModel(model.Object)).Returns(window);
|
||||
object parent = null;
|
||||
model.SetupSet(x => x.Parent = It.IsAny<object>()).Callback((object x) => parent = x);
|
||||
this.windowManager.CreateWindow(model.Object, true);
|
||||
|
||||
model.Setup(x => x.CanCloseAsync()).ReturnsAsync(true);
|
||||
((IChildDelegate)parent).CloseItem(model.Object);
|
||||
|
||||
model.Verify(x => x.Close());
|
||||
Assert.True(window.OnClosedCalled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue