diff --git a/xunit.runner.wpf/MainWindow.xaml b/xunit.runner.wpf/MainWindow.xaml index 5940406..304d941 100644 --- a/xunit.runner.wpf/MainWindow.xaml +++ b/xunit.runner.wpf/MainWindow.xaml @@ -105,6 +105,16 @@ + + + + + + + + diff --git a/xunit.runner.wpf/ViewModel/MainViewModel.cs b/xunit.runner.wpf/ViewModel/MainViewModel.cs index 93b6de8..9ef4e59 100644 --- a/xunit.runner.wpf/ViewModel/MainViewModel.cs +++ b/xunit.runner.wpf/ViewModel/MainViewModel.cs @@ -49,6 +49,7 @@ namespace xunit.runner.wpf.ViewModel this.WindowLoadedCommand = new RelayCommand(OnExecuteWindowLoaded); this.RunCommand = new RelayCommand(OnExecuteRun, CanExecuteRun); this.CancelCommand = new RelayCommand(OnExecuteCancel, CanExecuteCancel); + this.TraitSelectionChangedCommand = new RelayCommand(OnTraitSelectionChanged); } private static bool TestCaseMatches(TestCaseViewModel testCase, SearchQuery searchQuery) @@ -58,6 +59,24 @@ namespace xunit.runner.wpf.ViewModel return false; } + if (searchQuery.TraitSet.Count > 0) + { + var anyMatch = false; + foreach (var cur in testCase.Traits) + { + if (searchQuery.TraitSet.Contains(cur)) + { + anyMatch = true; + break; + } + } + + if (!anyMatch) + { + return false; + } + } + switch (testCase.State) { case TestState.Passed: @@ -88,6 +107,7 @@ namespace xunit.runner.wpf.ViewModel public ICommand WindowLoadedCommand { get; } public RelayCommand RunCommand { get; } public RelayCommand CancelCommand { get; } + public ICommand TraitSelectionChangedCommand { get; } public CommandBindingCollection CommandBindings { get; } @@ -364,8 +384,12 @@ namespace xunit.runner.wpf.ViewModel private void OnTestDiscovered(object sender, TestCaseDataEventArgs e) { var t = e.TestCaseData; - this.allTestCases.Add(new TestCaseViewModel(t.SerializedForm, t.DisplayName, t.AssemblyPath)); - this.traitCollectionView.Add(t.TraitMap); + + var traitMap = t.TraitMap.Count == 0 + ? ImmutableArray.Empty + : t.TraitMap.SelectMany(pair => pair.Value.Select(value => new TraitViewModel(pair.Key, value))).ToImmutableArray(); + this.allTestCases.Add(new TestCaseViewModel(t.SerializedForm, t.DisplayName, t.AssemblyPath, traitMap)); + this.traitCollectionView.Add(traitMap); } private void OnTestFinished(object sender, TestResultDataEventArgs e) @@ -405,6 +429,14 @@ namespace xunit.runner.wpf.ViewModel this.cancellationTokenSource.Cancel(); } + private void OnTraitSelectionChanged() + { + this.searchQuery.TraitSet = new HashSet( + this.traitCollectionView.Collection.Where(x => x.IsSelected), + TraitViewModelComparer.Instance); + FilterAfterDelay(); + } + public bool IncludePassedTests { get { return searchQuery.IncludePassedTests; } diff --git a/xunit.runner.wpf/ViewModel/SearchQuery.cs b/xunit.runner.wpf/ViewModel/SearchQuery.cs index 36f5da7..5900b67 100644 --- a/xunit.runner.wpf/ViewModel/SearchQuery.cs +++ b/xunit.runner.wpf/ViewModel/SearchQuery.cs @@ -11,7 +11,7 @@ namespace xunit.runner.wpf.ViewModel public bool IncludeFailedTests = true; public bool IncludePassedTests = true; public bool IncludeSkippedTests = true; - public string SearchString = string.Empty; + public HashSet TraitSet = new HashSet(TraitViewModelComparer.Instance); } } diff --git a/xunit.runner.wpf/ViewModel/TestCaseViewModel.cs b/xunit.runner.wpf/ViewModel/TestCaseViewModel.cs index ab6b7a0..3e5e321 100644 --- a/xunit.runner.wpf/ViewModel/TestCaseViewModel.cs +++ b/xunit.runner.wpf/ViewModel/TestCaseViewModel.cs @@ -1,6 +1,7 @@ using GalaSoft.MvvmLight; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.IO; using System.Linq; using System.Text; @@ -11,24 +12,28 @@ namespace xunit.runner.wpf.ViewModel { public class TestCaseViewModel : ViewModelBase { - public TestCaseViewModel(string testCase, string displayName, string assemblyFileName) + private TestState _state = TestState.NotRun; + + public TestCaseViewModel(string testCase, string displayName, string assemblyFileName, ImmutableArray traits) { this.TestCase = testCase; this.DisplayName = displayName; this.AssemblyFileName = assemblyFileName; + this.Traits = traits; } public string DisplayName { get; } - private TestState state = TestState.NotRun; public TestState State { - get { return state; } - set { Set(ref state, value); } + get { return _state; } + set { Set(ref _state, value); } } public string AssemblyFileName { get; } public string TestCase { get; } + + public ImmutableArray Traits { get; } } } diff --git a/xunit.runner.wpf/ViewModel/TraitCollectionView.TraitViewModelComparer.cs b/xunit.runner.wpf/ViewModel/TraitCollectionView.TraitViewModelComparer.cs deleted file mode 100644 index d8b9358..0000000 --- a/xunit.runner.wpf/ViewModel/TraitCollectionView.TraitViewModelComparer.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace xunit.runner.wpf.ViewModel -{ - public partial class TraitCollectionView - { - private sealed class TraitViewModelComparer : IEqualityComparer, IComparer - { - private readonly StringComparer _comparer = StringComparer.Ordinal; - - public int Compare(TraitViewModel x, TraitViewModel y) - { - var result = _comparer.Compare(x.Name, y.Name); - if (result != 0) - { - return result; - } - - return _comparer.Compare(x.Value, y.Value); - } - - public bool Equals(TraitViewModel x, TraitViewModel y) - { - return _comparer.Equals(x.Name, y.Name) - && _comparer.Equals(x.Value, y.Value); - } - - public int GetHashCode(TraitViewModel obj) - { - return obj.Name.GetHashCode(); - } - } - } -} diff --git a/xunit.runner.wpf/ViewModel/TraitCollectionView.cs b/xunit.runner.wpf/ViewModel/TraitCollectionView.cs index 30cacff..bb0f58d 100644 --- a/xunit.runner.wpf/ViewModel/TraitCollectionView.cs +++ b/xunit.runner.wpf/ViewModel/TraitCollectionView.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; @@ -10,7 +11,7 @@ namespace xunit.runner.wpf.ViewModel { public sealed partial class TraitCollectionView { - private readonly TraitViewModelComparer _comparer = new TraitViewModelComparer(); + private readonly TraitViewModelComparer _comparer = TraitViewModelComparer.Instance; private readonly ObservableCollection _collection = new ObservableCollection(); public ObservableCollection Collection => _collection; @@ -20,19 +21,16 @@ namespace xunit.runner.wpf.ViewModel } - public void Add(Dictionary> traitMap) + public void Add(ImmutableArray traitList) { - if (traitMap.Count == 0) + if (traitList.Length == 0) { return; } - foreach (var pair in traitMap) + foreach (var traitViewModel in traitList) { - foreach (var value in pair.Value) - { - TryInsert(new TraitViewModel(pair.Key, value)); - } + TryInsert(traitViewModel); } } diff --git a/xunit.runner.wpf/ViewModel/TraitViewModel.cs b/xunit.runner.wpf/ViewModel/TraitViewModel.cs index 72c7b46..11b2f1b 100644 --- a/xunit.runner.wpf/ViewModel/TraitViewModel.cs +++ b/xunit.runner.wpf/ViewModel/TraitViewModel.cs @@ -15,6 +15,7 @@ namespace xunit.runner.wpf.ViewModel public string Name => _name; public string Value => _value; public string DisplayName => $"{Name}={Value}"; + public bool IsSelected { get; set; } public TraitViewModel(string name, string value) { diff --git a/xunit.runner.wpf/ViewModel/TraitViewModelComparer.cs b/xunit.runner.wpf/ViewModel/TraitViewModelComparer.cs new file mode 100644 index 0000000..9970a0a --- /dev/null +++ b/xunit.runner.wpf/ViewModel/TraitViewModelComparer.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace xunit.runner.wpf.ViewModel +{ + internal sealed class TraitViewModelComparer : IEqualityComparer, IComparer + { + internal static readonly TraitViewModelComparer Instance = new TraitViewModelComparer(); + + private readonly StringComparer _comparer = StringComparer.Ordinal; + + public int Compare(TraitViewModel x, TraitViewModel y) + { + var result = _comparer.Compare(x.Name, y.Name); + if (result != 0) + { + return result; + } + + return _comparer.Compare(x.Value, y.Value); + } + + public bool Equals(TraitViewModel x, TraitViewModel y) + { + return _comparer.Equals(x.Name, y.Name) + && _comparer.Equals(x.Value, y.Value); + } + + public int GetHashCode(TraitViewModel obj) + { + return obj.Name.GetHashCode(); + } + } +} diff --git a/xunit.runner.wpf/xunit.runner.wpf.csproj b/xunit.runner.wpf/xunit.runner.wpf.csproj index 2812251..e8d4ace 100644 --- a/xunit.runner.wpf/xunit.runner.wpf.csproj +++ b/xunit.runner.wpf/xunit.runner.wpf.csproj @@ -94,7 +94,6 @@ LoadingDialog.xaml - @@ -102,6 +101,7 @@ + Designer